TypeScript极速入门
类型
const hello = (name: string) => {
return `hello${name}`
}
hello(111) //会提示错误
还有Object
any可以是任意类型
var notSure: any = true //any可以是任意类型
tsc 编译为 js
let arrNumber: number[] = [1, 2, 3, 'ddd'] //不能将类型“string”分配给类型“number”。
node hello.js
编译与运行结合
编译:
npm i tsc -g
tsc -v
若想要把编译与运行结合起来,可使用ts-node模块:
npm install -g ts-node
npm i -g tslib @types/node
# 防止报错
就可用以下命令运行了:
ts-node hello.ts
可以在根目录新建tsconfig.json
文件,更多配置参考官网
{
"compilerOptions": {
"watch": true, //自动修改编译代码
"removeComments": true, //删除源文件的注视
}
}
数组
除了上面那样,还有一种方式就是使用数组泛型,Array<元素类型>
:
let list: Array<number> = [1, 2, 3];
数组的强化:元祖
数组中放置不同类型的元素,在js中元祖是不存在的
元祖编译后还是数组
// 把类型放置在方括号中
let tuple: [string, number]
tuple = ['2', 1]
tuple.push(1)// 添加元素必须是规定类型的类型
tuple.push({})// 类型“{}”的参数不能赋给类型“string | number”的参数。
Void
void
类型像是与any
类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void
:
function warnUser(): void {
console.log("This is my warning message");
}
声明一个void
类型的变量没有什么大用,因为你只能为它赋予undefined
和null
:
let unusable: void = undefined;
interface接口
描述对象的形状
interface
具有描述较为复杂数据结构的能力
interface Person { //注意分号分隔
readonly id: number; //只读
name: string;
age?: number; //可选属性
}
let myx: Person = {
id: 1234, //赋值后,id再也不能被改变了
name: 'myx'
}
myx.id = 5; // error! 无法为“id”赋值,因为它是只读属性
函数和类型推断
// 函数和类型推断
// z为可选参数,可传可不传
function add(x: number, y: number, z?: number): string {
if (typeof z === 'number') {
return `${x + y + z} `
} else {
return `${x + y} `
}
}
let result = add(2, 3)
console.log('result---', result);
const add = function (x: number, y: number, z?: number): number {
if (typeof z === 'number') {
return x + y + z
} else {
return x + y
}
}
const add2: (x: number, y: number, z?: number) => number = add
接口形式设置函数形状
包括参数类型和返回值类型
interface ISum {
(a: string, b: string): string;
}
let sum: ISum //使用接口来限定某个变量为函数类型
sum = function name(a, b) { //赋值的函数那么就必须符合接口中限定的类型规则了
return a + b
}
sum('1', '2')
类型推论
即使在不明确指定类型的情况下
ts依然会根据当前变量中所保存的值的类型,推断出一个类型
联合类型
当一个变量需要多种类型的时候可以用 竖线
分隔开
自然的,只可以赋值为联合类型中的类型,否则报错
联合类型 一般用于限定函数的参数,
用于接受一个不确定类型的参数
如下图:在类型不确定的情况下,可以访问联合类型中的共有属性和方法,而访问非共有属性或方法是会报错的
类型断言
当在不确定当前变量的类型时,又需要访问其中一种类型的属性或者方法的时候就可以使用类型断言
类型断言采用 as
关键字
将变量强制喂联合类型中的其中一种,
就可以访问此中类型下的属性和方法了。
如果断言成非联合类型中的类型的话,就会报错。
泛型
定义函数的时候,通过将 占位符T
放在一对尖括号中
以此来制定一种动态的类型
之所以说是动态的,是因为具体是什么类型,要到函数调用的时候再来指定
定义好动态类型T后就可以在后面使用了,比如将函数的参数设置为T类型,返回值也设置为T类型,这种形式定义的类型就是泛型(含有广泛的类型的意思)
调用函数的时候就可以指定类型了
function fn<T>(params: T): T {
return params
}
fn(100)
fn('100')
fn(true)
复杂的泛型
例子:定义一个用于交换数组中两个元素位置的函数,返回值为互换位置的两个类型
泛型约束
此函数希望返回参数的length属性,函数返回值的类型当然应该为数值,
而函数的参数就必须是一个具有length属性的变量,这种情况下可以定义一个包含length属性的接口,然后可以使用这个接口来约束泛型T。
通过 extends + 接口名字来实现泛型约束的
// 泛型约束
interface WithLength {
length: number
}
function returnLength<T extends WithLength>(params: T): number {
return params.length //类型“T”上不存在属性“length”
}
returnLength('hello')
returnLength([1, 2, 3])
returnLength({ length: 100 })
returnLength(1) //类型“number”的参数不能赋给类型“WithLength”的参数
枚举
其实很好理解:
在js中一般用 const 来定义常量,但有些取值呢是在一定范围内的一系列常量
enum Direction {
Up,
Down,
left,
Right
}
console.log(Direction.Up); //0
console.log(Direction[0]); //Up
//枚举成员会被赋值为从0开始
枚举还做了一个反向映射,可以把这个枚举看成一个数组