npm i typescript -g
tsc --init
Boolean
number
string
undefined
null
any
- // Boolean
- let isDonn: boolean = true
- // number
- let num: number = 10
- // string
- let str: string = 'sssss'
- // undefined
- let unde: undefined = undefined
- // null
- let nul: null = null
- // any
- let age: any = 18
- age = '10'
- // 数组
- const arr: number[] = [1,2,3]
- // 元祖
- const arr2: [number, string] = [123, '123']
元祖:本质上其实就是数组,不过跟数组不一样的就是可以单独限制数组中的每个数据类型
- interface person {
- name: string,
- age: number,
- readonly jobNo: number, // 只读属性
- salary?: number // 可选属性
- }
-
- let yaoqi: person = {
- jobNo: 10001,
- name: 'yaoqi',
- age: 20
- }
通过interface关键字定义接口
属性前添加readonly表示只读属性
属性后加?问号表示可选属性
❝
变量不需要声明类型,根据赋值自定推论出变量类型
❞
- let str = 'abc' // 推论str为string类型
- // str = 123 // 会报警告
❝
联合类型就是可以指定多个类型
❞
- let strOrNum: string | number = 'abc' // 变量可以是多种类型
- strOrNum = 123
❝
当变量不确定是什么类型,但是我们知道会是什么类型时,可以断言为某种具体类型
❞
通过as关键字断言
- // 通过as关键字断言
- function getLength(input: string | number): number {
- let str = input as string // 断言input是string类型
- if(!str.length) {
- return input.toString().length
- }
- return str.length
- }
隐式断言
❝
不需要主动断言,ts会根据代码逻辑自动断言出类型
❞
- // 隐式断言
- function getLength2(input: string | number): number {
- if(typeof input === 'string') {
- // 已经隐式断言input为string
- return input.length
- } else {
- // 已经隐式断言input为number
- return input.toString().length
- }
- }
❝
枚举就是固定的几个值,比如每周的工作日,红绿灯的颜色。
类似数组,默认索引是从0开始的数字,索引可以修改。
❞
枚举
- // 枚举
- enum Direction {
- Up, // 0
- Down, // 1
- Left, // 2
- Right = '右' // 3
- }
-
- console.log(Direction.Up); // 0
- console.log(Direction[0]); // Up
- console.log(Direction['Right']); // 右
编译后的js代码
- // 枚举
- var Direction;
- (function (Direction) {
- Direction[Direction["Up"] = 0] = "Up";
- Direction[Direction["Down"] = 1] = "Down";
- Direction[Direction["Left"] = 2] = "Left";
- Direction["Right"] = "\u53F3"; // 3
- })(Direction || (Direction = {}));
- console.log(Direction.Up); // 0
- console.log(Direction[0]); // Up
- console.log(Direction['Right']); // 右
常量枚举
❝
在enum前面加一个const就可以变为常量枚举
常量枚举编译后的js代码量少,因为编译成了对应的值,没有枚举创建的过程了。
❞
- // 枚举
- const enum Direction {
- Up, // 0
- Down, // 1
- Left, // 2
- Right = '右' // 3
- }
- console.log(Direction.Up); // 0
- console.log(Direction['Right']); // 右
编译后的js代码
- console.log(0 /* Direction.Up */); // 0
- console.log("\u53F3" /* Direction['Right'] */); // 右
❝
定义函数、接口和类的时候不指定类型,使用的时候再定义类型
定义的时候先创建泛型名称,使用泛型代替类型,也就是泛型代指某一种具体类型。
❞
定义函数、接口和类的时候,在名称后面加上< >
来定义泛型,< >
里面加上泛型的名称
- // 泛型
- // 定义函数、接口和类的时候不指定类型,使用的时候再定义类型
- function echo
(arg: T): T { - return arg
- }
- // 根据传入的类型决定返回的类型
- const res = echo(123); // res等于number类型的123
- const res2 = echo('123'); // res2等于string类型的123
- console.log(typeof res, typeof res2); // number string
创建了一个名称为T的泛型,「T到底是什么类型不知道,可能是任何一种,具体是什么要看使用时传入的类型。」
arg: T 使用泛型T作为入参的类型
将泛型T作为函数返回值
定义多个泛型
- // 定义多个泛型
- // 示例:调换数组元素顺序的函数
- function swap
(tuple: [T, U]): [U, T]{ - return [tuple[1], tuple[0]]
- }
-
- const res3 = swap(['str', 123])
- console.log(typeof res3[0]); // number
- console.log(typeof res3[1]); // string
❝
通过泛型约束传入的参数中必须包含某个属性,通过添加
extends
关键字约束泛型。❞
- function echoLength
(arg: T) :T{ - console.log(arg.length); // 这里会报一个警告:类型“T”上不存在属性“length”
- return arg
- }
上面的函数中会报一个警告:类型“T”上不存在属性“length”。
如果泛型T是string或者array没问题,因为本身就有length,但如果是number就会报错,因为number没有length属性。因为ts不知道泛型T会是什么类型,所以也就不知道arg上面会不会有length属性。
如果使用「泛型约束」就可以很好的解决上面得问题,因为可以约束泛型T必须包含length属性。
「通过extends
关键字约束泛型」
- interface IWithLength {
- length: number
- }
- function echoLength
extends IWithLength>(arg: T) :T{ - console.log(arg.length); // 这里会报一个警告:类型“T”上不存在属性“length”
- return arg
- }
- const str = echoLength('str') // 3
- const obj = echoLength({ length: 8 }) // 8
「在类中的使用」
- class Queue
{ - // 数组
- private data:T[] = []
- // 添加item
- add(item: T) {
- return this.data.push(item)
- }
- }
- // 创建一个number的数组,添加的也必须是number
- const queue = new Queue
() - queue.add(123)
- // 创建一个string的数组,添加的也必须是string
- const queue2 = new Queue
() - queue2.add('123')
「在接口中的使用」
- interface keyPair
{ - key: T,
- value: U
- }
- // key为number,value为string
- const data:keyPair
= { - key: 13,
- value: 'enter'
- }
- // key为string,value为number
- let data2:keyPair
- data2 = { key: 'enter', value: 13 }
「通过泛型创建数组」
let dataList:Array
❝
有些类型名称比较长,就是给类型起一个别的名称
❞
- // 定义一个传入值为number,返回值也是number的函数
- let fn: (x: number, y: number) => number
如果多个函数都是这样的类型就需要写很多次,可以给这个类型定义一个别名使用
- type funcType = (x: number, y: number) => number
-
- let fn1: funcType
- let fn2: funcType
- type numOrStr = number | string
-
- const data1: numOrStr = 123;
- const data2: numOrStr = 'abc';
❝
创建固定值的类型,自己创建一个类型,这个类型是固定的值,可以是多个值。
❞
- const myName: 'Jack' = "Jack"
-
- let sex:'男'|'女'
- sex= '男'
「字面量的使用」
- type trafficLight = '红灯'|'绿灯'|'黄灯'
- const red:trafficLight = "红灯"
❝
对某个类型进行扩展组合成为新的类型
❞
「类和接口的交叉类型」
- interface man { age: number }
-
- type Iperson = { name: string } & man // 将interface和类合并成一个新的交叉类型
-
- let person:Iperson = {
- name: 'Jack',
- age: 18
- }
「type和interface的区别」
type是某个类型的别名,当类型的名称太长或想起另一个名称时使用
interface是一个标准的类型接口
「global objects(全局对象)」
- let arr: Array
= [1, 2, 3] -
- let date: Date = new Date()
-
- let reg: RegExp = /name/
「build-in object(内置对象)」
Math.pow(2,3)
「Dom and Bom(DOM和BOM标准对象类型」
- let body: HTMLElement = document.body;
- let lis: NodeListOf<HTMLElement> = document.querySelectorAll('li')
- lis.keys()
「Utility Types(功能性类型)」
Partial:把传入的类型都变成可选类型
- interface IPerson {
- name: string,
- age: 18
- }
- // let jack:IPerson = { name: 'jack' } // 警告:缺少age
-
- type IPartial = Partial<IPerson> // Partial将IPerson属性转为可选
-
- let jack:IPartial = { name: 'jack' }
Omit: 忽略传入的某个属性
- interface IPerson {
- name: string,
- age: 18
- }
- type IOmit = Omit<IPerson, 'name'> // 忽略掉IPerson中的name属性
-
- // let jack:IOmit = { name: 18 } // 警告:对象字面量只能指定已知属性,并且“name”不在类型“IOmit”中
- let jack:IOmit = { age: 18 }