Skip to content
On this page

本文内容主要来自玩转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,并不完全 编译期泛型.