Appearance
本文内容主要来自玩转vue3全家桶
课程.
联合类型定义
typescript
let course1 : string|number = 3 //course的类型可以是string以及number,其他则是错误.
泛型
语言引入泛型后,不可避免的复杂化.
最简单的泛型
typescript
function identity<T>(arg: T): T {
return arg
}
泛型的一些关键字
keyof
keyof keyof T
获取T的所有key,相当于返回一个字符串列表,其中每一个字符串都是T的key
ts
type CourseProps = keyof VueCourse5 // 只能是name和price选一个
let k:CourseProps = 'name'
let k1:CourseProps = 'p' // 改成price
类型三元表达式
extends 关键字 T extends U? X:Y
主要这里的T,U,X,Y都是类型,而不是数值
ts
type MyType<T>= T extends boolean?String:Number
type MyTypeString=MyType<boolean> //MyTypeString类型实际上是String 等价于type MyTypeString=String
type MyTypeNumber=MyType<string> //MyTypeString类型实际上是Number,等价于type MyTypeNumber=Number
in 关键字
in 用于类型中
ts
type Courses = '玩转Vue 3'|'重学前端'
type CourseObj = {
[k in Courses]:number // 遍历Courses类型作为key
}
// 上面的代码等于下面的定义
// type CourseObj = {
// 玩转Vue 3: number;
// 重学前端: number;
// }
组合起来的getProperty
这里的extends和上面说的并不一致, K extends key of T
限定了K的类型是一个字符串常量列表,其中每一个字符串都是T的field名字. T[K]
则表示T的field K的类型
ts
function getProperty(<T,K extends keyof T>)(obj:T, field:K):T[K]{
return obj[field];
}
infer关键字
来自知乎
infer关键字用于类型解构,想得到一个类型的某部分的类型,可以使用infer.
ts
type ReturnType<T> = T extends ()=>infer R? R:any
这里的T如果infer,比如 T extends ()=>string
表示T是一个返回类型是string的函数,但是我想取这个函数类型的返回值类型,该怎么办呢? 就用infer R
,相当于引入了一个新类型,该类型表示T
的某一个局部的类型.
更多例子
ts
type Partial<T> ={
[K keyof T]?: T[K] //注意这里的?,
}
//Exclude from T those types that are assignable to U
type Exclude<T,K> =T extends K? never: T
//Construct a type with a set of properties K of type T
type Record<K extends key of any,T>={
[P in K]: T;
}
// From T, pick a set of properties whose keys are in the union K
type Pick<T,K extends keyof T> ={
[P in K]:T[P];
}
一个完整的例子
ts
import axios from 'axios'
interface Api{
'/course/buy':{
id:number
},
'/course/comment':{
id:number,
message:string
}
}
function request<T extends keyof Api>(url:T,obj:Api[T]){
return axios.post(url,obj)
}
request('/course/buy',{id:1})
request('/course/comment',{id:1,message:'嘎嘎好看'})
request('/course/comment',{id:1}) //Argument type {id: number} is not assignable to parameter type Api["/course/comment"]
request('/course/404',{id:1}) //Argument type "/course/404" is not assignable to parameter type keyof Api
更多类型编程
这玩意感觉类似于针对类型的编程语法,有点象高级宏,和普通编程的思路是不太一样的. 更多的例子到type-challenges. 这也是c++,Rust等语言在支持泛型后,不可避免带来的复杂化问题. 而Java的泛型则实际上是动态执行的时候都会转换成Object,并不完全 编译期泛型.