ts 类型
协变和逆变的区别,如果你不理解或没听说过这两个词,建议你记住结论就行了:infer类型推导,函数参数的位置是交叉类型,其他位置都是联合类型。
获取对象全部路径(包含深度路径)
这个类型定义中,通过 [K in keyof T]``,遍历了 T对象中的每个属性K,然后通过 K extends string ?来判断K是否为字符串类型,如果是,则继续判断T[K]是否是一个嵌套的对象类型,如果是,则返回K.{K}.K.{Path<T[K]>},这里使用了递归调用 Path<T[K]>来处理多层嵌套属性。如果T[K]不是嵌套的对象类型,则返回属性名K。如果 K不是字符串类型,则返回never`。
typescript
type Path<T> = {
[K in keyof T]: K extends string
? T[K] extends Record<string, any>
? `${K}.${Path<T[K]>}`
: K
: never
}[keyof T]
interface IConfig {
host: string
port: string
db: {
host: string
port: number
}
}
type IConifgPath = Path<IConfig> // "host" | "port" | "db.host" | "db.port"联合类型转 tuple
reference
ts
type UnionToIntersection<T> = (T extends infer R ? (fn: () => R) => void : never) extends (
a: infer S
) => void
? S
: never
type IntersectionLast<T> = T extends () => infer R ? R : never
type UnionLast<T> = IntersectionLast<UnionToIntersection<T>>
type UnionToTuple<T, R extends Array<unknown> = [], L = UnionLast<T>> = [T] extends [never]
? R
: UnionToTuple<Exclude<T, L>, [...R, L]>
UnionToTuple<'a' | 'b'> // ['a', 'b']柯里化
typescript
type Curried<A, R> = A extends []
? () => R
: A extends [infer ARG]
? (params: ARG) => R
: A extends [infer ARG, ...REST]
? (params: ARG) => Curried<REST, R>
: never
declare function curry<A extends any[], R>(fn: (...args: A) => R): Curried<A, R>全局类型定义
jquery
declare const $: any
注意该声明所在文件应该被 tsconfig.json include
具名导出
ts
// types.d.ts
declare module 'my-library' {
export function myFunction(param: string): number
export const myConstant: string
export interface MyInterface {
prop1: string
prop2: number
}
}npm 依赖
ts
declare module 'eslint-plugin-react-hooks' {
const hooks: Record<string, any>
export default hooks
export const someProperty: number
}默认导出包含多个属性
ts
// my-library.js
export default {
myFunction(param) {
return param.length
},
myConstant: 'Hello',
}
// types.d.ts
declare module 'my-library' {
interface MyLibrary {
myFunction(param: string): number
myConstant: string
}
const lib: MyLibrary
export default lib
}
// 使用
import myLibrary from 'my-library'
const result = myLibrary.myFunction('hello') // result 的类型是 number
console.log(myLibrary.myConstant) // myConstant 的类型是 string复杂对象
ts
// my-library.js
export default {
version: '1.0.0',
utils: {
add(a, b) {
return a + b
},
},
}
// types.d.ts
declare module 'my-library' {
interface Utils {
add(a: number, b: number): number
}
interface MyLibrary {
version: string
utils: Utils
}
const lib: MyLibrary
export default lib
}
// 使用
import myLibrary from 'my-library'
console.log(myLibrary.version) // version 的类型是 string
const result = myLibrary.utils.add(1, 2) // result 的类型是 number默认导出 Class
ts
// my-library.js
export default class MyClass {
constructor(value) {
this.value = value
}
getValue() {
return this.value
}
}
// types.d.ts
declare module 'my-library' {
class MyClass {
constructor(value: string)
getValue(): string
}
export default MyClass
}
// 使用
import MyClass from 'my-library'
const instance = new MyClass('hello')
const value = instance.getValue() // value 的类型是 string默认导出函数 + 额外属性
ts
// my-library.js
function myFunction(param) {
return param.length
}
myFunction.myConstant = 'Hello'
export default myFunction
// types.d.ts
declare module 'my-library' {
interface MyFunction {
(param: string): number
myConstant: string
}
const myFunction: MyFunction
export default myFunction
}
// 使用
import myFunction from 'my-library'
const result = myFunction('hello') // result 的类型是 number
console.log(myFunction.myConstant) // myConstant 的类型是 string支持数组或对象解构
typescript
type ConvenientDeconstruction<T> = [any[], T] & { state: any[] } & T
declare function get<T>(): ConvenientDeconstruction<T>
const [state, { getState, setState }] = get<{ getState: () => any; setState: (v: any) => void }>()
// const { state, getState, setState } = get<{ getState: () => any, setState: (v: any) => void }>()