Typescript 基本使用

文章介绍了TypeScript如何解决JavaScript中的类型不明确问题,通过指定变量、函数参数和返回值的类型,以及对象、数组和枚举的类型限制,增强代码的可维护性和健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么需要Typescript

在编写Javascript代码时,会出现 类型不明确 或 函数参数不明确的问题。 比如我们可以对一个变量赋各种类型的值,也可以给一个函数传入各种类型的参数没,如下所示:

let a = 100

a = 'hello'

function add(x,y){
    return x+y
}

console.log(add(100,200)) //300
console.log(add(100,'200')) // '100200'


这会带来一些混乱,比如我们实现了一个函数add用来实现加法,我们期待用户能传入两个number类型的值,但是当用户传入number和string类型时,返回的结构就不会符合预期。所以需要对变量,参数等类型进行限制。

TypeScript 是一种基于 JavaScript 构建的强类型编程语言, 可以理解为js的扩展,增加了对于js中宽松的类型的限制。但是需要注意,TypeScript无法直接运行在浏览器或者nodejs环境中,需要使用ts专用的编译器(或者webpack ts-loader/Babel)将ts代码转换成js运行。

npm install  typescript 安装ts编译工具

 编写ts与编写js类似,我们创建xxx.ts文件来代替xxx.js 并在其中书写ts代码。

将上述代码改写成ts代码,我们可以发现,在试图修改number类型变量时和在向add函数中传入错误类型参数时会产生ts报错

指定变量类型

js中的值有类型,但是变量没有类型,可以指向任何类型的值, 但是在ts中,变量也是有类型的,并且只能赋予满足其类型的值,其具体写法为:

 var/const/let 变量名: 变量类型 = 值

如 let a: number = 100 表示a变量只能赋予数字类型的值,否则会报错。

当然,如果在声明变量时直接赋值,会默认变量为赋予值的类型,如 let a = 100 等价于上面的写法。

如果即不显式声明变量的类型,也不赋初始值,如 let a ;  则默认变量的类型为any,此时ts的检查无效 ,a可以赋予任何值。

限制函数类型

函数会限制两个部分,一个是参数类型,一个是返回值类型 ,一般可以采用如下写法

function 函数名称(参数: 类型,参数: 类型 ...): 返回值类型 {函数代码}

const 函数名: (参数: 类型,参数: 类型 ...) => 返回值类型 = function(参数..){函数代码}

例如,上面的add函数,可以采用如下的写法, 表示传入两个数字类型的参数,返回一个数字类型的值,这样在传入的值和参数类型不一致时,会产生ts报错来提示调用者。

function add(x: number,y: number): number{
     return x+y
}

const add: (x: number,y: number) => number = function(x,y){
    return x+y
}

const add: Function = function(x,y){
    return x+y
}

使用Function也可以来判断一个变量是否为函数类型,但是这样使用无法限制函数的参数和返回值,意义不大,一般不会这样使用。 

限制对象的类型

最简单的限制对象方式,可以直接使用object,如const obj: object = {} 但是同Function一样,这样只能限制赋给obj的不是个简单类型,赋一个函数 或者任意属性的对象都不会报错,这样的意义不大。

通常情况下,我们使用如下方式来限制对象的结构

const obj: {
    name: string,
    age: number,
    gender: string,
    score: number
} = {
    name: 'bill',
    age: 18,
    gender: 'male',
    score: 100
}

obj 的类型中,规定了其每个属性的名称和对应value的类型,赋给obj的值也必须同该类型具有相同的结构,否则会报错。

如何定义一个任意属性对象的类型?

你可能会想到使用 object,但是object的检查太宽泛了,你甚至可以给object类型的变量传递一个函数, 通常,我们使用以下的方法

1. 使用类型索引
const obj: {
    [P: string]: any
} = {
    name: 'bill',
    a:1,
    B:2,
    c:3,
    d: 'hello world!'
}

[P :string] 为类型索引,表示属性值可以是任何字符串类型,value为any,表示值可以是任何类型

2. 使用Record<k,v> 
const obj: Record<string,any> = {
    name: 'bill',
    a:1,
    B:2,
    c:3,
    d: 'hello world!'
}
Record<属性类型,值类型> 如上方式也可以定义一个任意类型的对象

如果想要求obj中必须包含一些属性,可以使用
const obj: {
    name: string,
    [P: string]: any
} = {
    name: 'bill',
    a:1,
    B:2,
    c:3,
    d: 'hello world!'
}

或者使用交叉类型
const obj: {name: string}&Record<string,any> = {
    name: 'bill',
    a:1,
    B:2,
    c:3,
    d: 'hello world!'
}

字面量限制 

如 const a: 10 = 10 那么a 只能为数字10 若赋值a=11会报错

也可以结合联合类型 const a: 1|2|3|4|5 = 1 (可以是 1, 2, 3,4,5中任意一个)

unknown any never

any代表任意类型,设置为any类型的变量相当于关闭ts类型检测,可以赋任何值,并且可以将其赋给任何变量。 尽量避免使用any的情况。但是并不是说不能用any,对于实在无法写出类型的,可以使用any,但是要避免"any一把梭"的情况!

unknown代表不知道的类型,和any类似,区别在于,any类型的变量可以赋任何类型的值,并且可以赋给任何类型的变量。unknow类型的变量虽然可以赋任何类型的值,但是在赋给其他非unknown类型的变量时,会报错,如:

unknow可以有效避免未知类型传递下去,面对未知的类型,unknown相比any是更好的选择

never表示逻辑上不应该发生的情况,我们在工作中不会常遇到使用 never 的情况

never可以赋给任何类型的变量,但是其自身不允许赋予任何非never类型的值或者变量

never出现的情况可能是:

// 如 不存在一个数满足  又是1 又是 2 又是 3
const a:1&2&3 = 1 // a never

// 如Exclude把所有的值都排除
type TType = Exclude<"name"|"age",'name'|'age'> // TType never

或者 一个函数不会返回值,如抛出异常,那么这个函数的返回值应该是never,需要注意void和never的区别,不写return 返回null undefined 都属于返回值为void 但是抛出异常中断函数属于never(逻辑上的错误)

function foo(): never{
    throw new Err()
}

交叉类型"&" 和 联合类型 "|"

交叉类型& 表示必须满足所有子类型 如

let a: 1&2&3&4 
// a为never 因为没有任何一个值满足 1&2&3&4

let obj: {name: string}&{age: number}&{gender: string}
// 这里等价于
let obj: {
    name: string,
    age: number,
    gender: string.
}
// 也就是说,三个类型都必须要满足,要包含name age gender

obj = {
    // 报错,少任何属性 或者多出来任何属性都不行
    name: 'bill',
    age: 18,
}

联合类型| 表示满足任意一个或多个子类型即可 如:

const a: 1|2|3|4|5|'hello' = 'hello'
// 这里a为 1,2,3,4,6,'hello'都可以

let obj:{age: number}|{score: number}|{name: string} = {
    // 满足 {age: number}|{score: number}|{name: string}
    name: 'bill',score: 100 ,age:18
}
// 这里obj中的属性,为三个子类型任意一个或者多个都可以
obj = {
    age: 18, // 满足{age: number}
}

obj = {
    // 满足 {age: number}|{name: string}
    name: 'jack',
    age: 18,
}

obj = {
    name: 'jack',
    age: 18,
    a: 1     // 多出一个属性,相当于 a: {name: string,age; number,a: number} 不满足任何子类型的组合
}

obj = {
    name: 'jack',
    age: '18'  // 类型错误,相当于 a: {name: string,age; string} 不满足任何子类型的组合
}

注意⚠️  never和任意类型的联合类型,都会去掉never 如 

let a: never|any // a为any

never和任何类型的交叉类型 都是 never 

let a: never|any // a为never

数组限制 

Javascript中的数组不会限制数组元素类型的一致性, 但是我们使用的时候最好统一数组项的类型,ts中可以使用 类型[] 的方式限制 或者使用 Array<Type> 表示某个类型的数组

const list: number[] = [1,2,3,4,5,6,7,8,9,10]

const list :Array<number> =[1,2,3,4]

ts还可以限制数组的长度,通常称为元组tuple ,其使用方法为 [项1类型,项2类型,... 项N类型]

类型需要一一对应

const tuple: [string,string]=['hello','world']

枚举enum

ts中支持枚举的定义,其具体定义形式为:

enum EnumName{
 枚举值定义
 key = value
}

如,定义性别枚举 
enum EGender{
    "male" = 0,
    "famale" = 1
}

使用 
const info: {
    name: string,
    age: number,
    gender: EGender
} = {
    name: 'bill',
    age: 18,
    gender: EGernder.male
}

注意,enum在ts编译成js之后是会生成一个对象的,可以在js中使用,但是其他的ts类型在编译成js之后会消失,无法在js中使用一个类型

类型别名 type

ts中支持把一个类型保存下来,使用type关键字,可以将类型,或者多个类型的联合或者交叉的结果暂存,方便灵活使用 如下:

type MyType = 1 | 2 | 3 | 4 |5 ;

const mytype: MyType = 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值