TypeScript的安装和使用
TypeScript的安装和使用
安装
npm i typescript
yarn add typescript
运行
首先安装ts-node
npm i ts-node
yarn add ts-node
运行ts文件:ts-node XXX.ts 类比node运行js文件
基础类型
//1. boolean
let trueOrFalse:boolean = true
//2. number
let num1:number = 1
//3. string
let str1:string = "字符串类型"
//4. undefined 和 null
let u:undefined = undefined
let n:null = null
//默认情况下 null和undefined为所有类型的子类型,可以进行赋值
//5. any 不清楚什么类型,不做过多叙述,非必要不推荐使用
//6. unknown u代表任何类型,它的定义和 any 定义很像,但是它是一个安全类型,使用 unknown 做任何事情都是不合法的。
//7. void 表示没有任何类型
//8. never 表示那些用不存在的值
//9. 数组
let list:number[] = [1,2,3] //内部元素必须是数字,不是则会报错
let list2:Array<number> = [1,2,3]
//10. 元组
let tuple:[number,string] = [18,"阿巴阿巴"]
//可以使用push方法推入相同的类型
tuple.push(123) //不是则会报错
tuple.push(true) //会报错
//11. 函数
function add(num1:number,num2:number):number{
return num1+num2
}
//箭头函数写法
const addFn=(num1:number,num2:number):number=>{
return num1+num2
}
interface
- TS设计出来用于定义对象类型的,可以对对象的形状进行描述
-
interface Person { name:string, age:number } // 一定要一一对应,类型对应,否则会发生报错 const p1:Person = { name:"卢本伟!" age:19 }
- 属性可选 ?标识
interface Person{ name:string, age?:number } //不写age也不会报错 const p1:Person = { name:"我靠" }
- 只读属性,不希望属性更改 readonly
interface Person{ readonly id:number name:string age:number } const p1:Person = { id:1 name:"string", age:18 } p1.id = 2 //报错
- interface描述函数类型
interface IAdd{ (x:number,y):number } const add:IAdd = (num1,num2) => { return num1 + num2 }
枚举
- 基本使用
enum Direction { up, down, left, right } //特点:数字递增 枚举成员会被赋值为从0开始递增的数字 Direction.up //0 Direction.down //1 Direction.left //2 Direction.right //3 // 枚举会对枚举名反向映射 Direction[0] //up Direction[1] //down Direction[2] //left Direction[3] //right //如果枚举第一个元素赋有初始值,那么会从初始值进行递增
- 反向映射的原理
const Direction (function(Direction){ Direction[Direction("up")=0] = "up" Direction[Direction("down")=1] = "down" Direction[Direction("left")=2] = "left" Direction[Direction("right")=3] = "right" })(Direction||(Direction = {})) //主体代码被包含在一个自执行函数里,封装自己独特的作用域 //执行如下代码 Direction[Direction("up")=0] = "up" //相当于 Direction["Up"] = 0 Direction[0] = "Up"
高级类型
-
联合类型
let mix:number|string num = 123 num = "abc" //只能访问公用方法,如果不是共用方法那么则会报错
-
交叉类型
interface Person{ name:string age:number } //这种写法让Teacher继承了Person的属性,type则是类型别名的表示 type Teacher = Person & {project:string}
联合类型是取几种类型中的任意一种,而交叉类型则是把几种类型合并起来
-
类型断言
function getLength(text:string|number):number{ const str = text as string //强制规定str是字符串类型 if(str.length){ return str.length }else{ const number = text as number return number.toString().length } }
-
泛型(对类型进行编程)
- 我们先简单举个例子
//这是我们JS定义的函数,并没有进行类型约束 function id(arg){ return arg } //我们来给他加上类型 规定输入类型和输出类型同为Number类型 function id(arg:number):number{ return arg } //这种方式的缺点相当明显,就是只能处理Number类型,无法拓展和通用 //有人可能说可以用any来替代,但是这同时也让类型失去原有的意义,不在进行类型保护
- 改进方法:T作为占位符填充类型
//这种就是所说的泛型,可以将<T>规定的类型链式传递给参数类型和返回类型 function id<T>(arg:T):T{ return arg } id<number>(123) //number将向下传递 id<string>("怎么说呢") //同理 /** * T代表Type ,定义泛型时通常用作第一个类型变量名称,除了T之外,还有如下 * 1. K(Key):表示对象中的键类型 * 2. V(Value):表示对象中的值类型 * 3. E(Element):表示元素类型 */ //定义多个类型变量 function identity<T,U>(value:T,message:U):T{ console.log(message) return value }
- 泛型接口
interface Identities<V, M> { value: V, message: M } function identity<T, U>(value: T, message: U): Identities<T, U> { console.log(typeof (value)) //number console.log(typeof (message)) //string let identities: Identities<T, U> = { value, message } return identities } console.log(identity(123,"HASHI"))
- 泛型约束
- 确保属性是存在的
interface Length{ length:number } function id<T extends Length>(arg:T):T{ console.log(arg.length) //通过继承的方式确保属性存在 return arg } //还可以通过 “,” 分隔多种约束类型 例 <T extends Length,Type2,Type3>
- 检查对象上的键是否存在
interface Person{ name:string, age:number, sex:string } type K1 = keyof Person; // "name" | "age" | "location" type K2 = keyof Person[]; // number | "length" | "push" | "concat" | ... type K3 = keyof { [x: string]: Person }; // string | number // 通过K extends keyof T 确保参数key一定是对象中含有的键 function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } let tsInfo = { name: "Typescript", supersetOf: "Javascript", difficulty: Difficulty.Intermediate } let difficulty: Difficulty = getProperty(tsInfo, 'difficulty'); // OK let supersetOf: string = getProperty(tsInfo, 'superset_of'); // Error
- 泛型条件类型
T extends U ? X : Y
-
常用泛型工具
- Partial 将某个类型里的属性全部变为可选项?
//定义方法 type Partial<T> = { //keyof T 拿到所有属性名 ,通过in进行遍历 再将值赋值给P,通过T[P]获取相应的属性值,?则是将所有属性变成可选 [P in keyof T]?:T[P] } interface Person { name: string, age: number, sex: string } //并不会报错 const p1: Partial<Person> = { name: "123" }
- Record 将K中所有的属性的值转化为T类型
//定义方法 type Record<K extends keyof any,T> = { [P in K]:T } interface PageInfo{ title:string } type Page = "home" |"about" |"contact" const x:Record<Page,PageInfo> = { about:{title:"about"}, contact:{title:"contact"}, home:{title:"home"} }
- Pick 将某种类型中的子属性挑出来,变成包含这个类型部分属性的子类型
//定义方法 type Pick<T,K extends keyof T>={ [P in K]:T[P] } interface Todo{ title:string, age:number, isFinished:boolean } type TodoPreview = Pick<Todo,"title"|"isFinished" const x:TodoPreview = { title:"阿哲", isFinished:false }
- Exclude 将某个类型中属于另一个的类型移除掉
//定义方法 type Exclude<T,U>= T extends U ? never:T type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c" type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c" type T2 = Exclude<string | number | (() => void), Function>; // string | number
- ReturnType 获取函数T的返回类型
type ReturnType<T extends(...args:any)=>any> = T extends (...args:any) = >infer R? R;any type T0 = ReturnType<() => string>; // string type T1 = ReturnType<(s: string) => void>; // void type T2 = ReturnType<<T>() => T>; // {} type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // number[] type T4 = ReturnType<any>; // any type T5 = ReturnType<never>; // any type T6 = ReturnType<string>; // Error type T7 = ReturnType<Function>; // Error
- Partial 将某个类型里的属性全部变为可选项?