这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战
别名中的类型转换
Exclude<Type, ExcludedUnion>
“排除”:通过从 Type 中排除所有可分配给 ExcludedUnion 的类型构造一个类型
例 :
type Attrs = 'height' | 'width' | 'border' | (() => void)
type SomeAtts = Exclude<Attrs, 'border' | Function>
let a: SomeAtts = 'height'
解析:从别名中 Attrs 中排除了‘border’和‘Function’构造出新的类型别名;
Extract<Type, Union>
“提取”:通过从 Type 中提取可以分配给 Union 的所有类型来构造类型
例 :
type attrs = 'height' | 'width' | 'border' | (() => void)
type SomeAtts = Extract<attrs, 'font' | Function>
a = function name( ) { }
解析:attrs中可以分配给Union的类型只有Function;新的类型SomeAttrs实际被转换为type SomeAttrs = Function 。Extract实际上就是获取两者的交集构造新的类型。
上面的两个例子中提到的 Function 和 (() => void) 都表示方法、函数
NonNullable
通过从 Type 中排除 null 和 undefined 来构造一个类型
type attrs = 'height' | 'width' | (() => void) | null | undefined
type SomeAtts = NonNullable<attrs>
解析:新别名SomeAtts中不包含 undefined 和 null
函数中的类型转换
Parameter
“参数”:从函数类型 Type 的参数中使用的类型构造元组类型(提取函数中的参数类型,构造成一个数组类型)
例子一
type Case = Parameters<() => string>;
// type Case = []
let a: Case = []
解析: 将一个参数为空返回值为string的函数类型转换为一个空数组类型。
例子二
type Case = Parameters<(s: string) => void>;
// type Case = [s: string]
let b: Case = ['sdf']
解析: 将一个参数为一个字符串类型返回值为void的函数类型转换为只有一个字符串项的数组类型
例子三
type Case1 = Parameters<<T>(arg: T) => T>;
// type Case1 = [arg: unknown]
type Case2 = Parameters<any>;
// type Case2 = unknown[]
let d: Case1 = ['']
let c: Case2 = [1, 2, 3]
解析: 上面的Case1 和 Case2 都是转换为未知的数组类型。
但是 Case1 是转换为长度为一的元素类型未知的数组类型。
Case2 是转换为 长度未知,元素类型未知的未知数组类型;
例子四
type Case5 = Parameters<never>;
// type Case5 = never
解析: 转换为 never 类型
错误例子
type Case6 = Parameters<string>;
// type Case6 = never
type Case7 = Parameters<Function>;
// type Case7 = never
//Error: Caseype 'string' does not satisfy the constraint '(...args: any) => any'.
//Error: Caseype 'Function' does not satisfy the constraint '(...args: any) => any'.
解析: 如果强制转换,那么转换结果也是 never 类型;
ReturnType
“返回类型”:构造一个由 Type 函数的返回值类型组成的新类型。
例一
type Case = ReturnType<() => string>;
// type Case = string
type Case2 = ReturnType<<T>() => T>;
// type Case2 = unknown
解析: 将原类型转换为返回值的类型(即为string类型);当返回值为未知类型时,转换为未知类型;
例二
type T3 = ReturnType<<T extends U, U extends number[]>() => T>;
// type T3 = number[]
解析: T继承自U,U继承自数字类型数组,所以T为数字number类型数组的子集。依然属于number数组类型。
例三
declare function f1(): { a: number; b: string };
type T4 = ReturnType<typeof f1>;
// type T4 = {
// a: number;
// b: string;
// }
解析: 声明了函数f1,函数返回值为一个包含两个键值对的对象。返回值的类型为新的类型。
例四
type T5 = ReturnType<any>;
// type T5 = any
解析: 任意any类型
例五
type T6 = ReturnType<never>;
// type T6 = never
解析: never类型
错误例子
type T7 = ReturnType<string>;
// type T7 = any
type T8 = ReturnType<Function>;
// type T8 = any
Error: Type 'string' does not satisfy the constraint '(...args: any) => any'.
Error: Type 'Function' does not satisfy the constraint '(...args: any) => any'.
Error: Type 'Function' provides no match for the signature '(...args: any): any'.
解析: 和Parameters方法类似,没有返回值报错;强制转换的结果为any;
ThisParameterType
提取函数类型的 this 参数的类型,如果函数类型没有 this 参数,则未知。
declare function fn(): { a: number; b: string };
type F = ThisParameterType<typeof fn>
// type F = unknown
function fn2(this: number) { }
type F2 = ThisParameterType<typeof fn2>
// type F2 = number
解析: this必须要在参数中指明类型,才可以提取。提取后构造为新的类型。
OmitThisParameter
// 从 Type 中删除 this 参数,创建一个没有this参数的新函数类型。 如果 Type 没有显式声明this参数,则不对 Type 进行处理。
function fn(this: number): number{ return this }
type F = OmitThisParameter<typeof fn>
// type F = () => number
ThisType
此实用程序不返回转换后的类型。相反,它充当上下文这种类型的标记。请注意,必须启用 --noImplicitThis 标志才能使用此实用程序。
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
};
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
let data: object = desc.data || {};
let methods: object = desc.methods || {};
return { ...data, ...methods } as D & M;
}
let obj = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx; // Strongly typed this
this.y += dy; // Strongly typed this
},
},
});
obj.x = 10;
obj.y = 20;
obj.moveBy(5, 5);
翻译:
在上面的例子中,makeObject 参数中的方法对象有一个上下文类型,包括 ThisType<D & M> 因此方法对象中方法中的 this 类型是 { x: number, y: number } & { moveBy (dx: number, dy: number): number }. 请注意,methods 属性的类型如何同时是方法中此类型的推理目标和源。 ThisType 标记接口只是一个在 lib.d.ts 中声明的空接口。除了在对象字面量的上下文类型中被识别之外,该接口的作用类似于任何空接口。
ConstructorParameters
从构造函数类型的类型构造元组或数组类型。它生成一个包含所有参数类型的元组类型(或者如果 Type 不是函数,则类型 never )
type T0 = ConstructorParameters<ErrorConstructor>;
// type T0 = [message?: string]
type T1 = ConstructorParameters<FunctionConstructor>;
// type T1 = string[]
type T2 = ConstructorParameters<RegExpConstructor>;
// type T2 = [pattern: string | RegExp, flags?: string]
type T3 = ConstructorParameters<any>;
// type T3 = unknown[]
InstanceType
构造一个由 Type 中构造函数的实例类型组成的类型
class C {
x = 0;
y = 0;
}
type T = InstanceType<typeof C>;
let a: T = {
x: 1,
y: 2
}
解析: 将类C实例后转化为新的类型;
字符串中的类型转换
Uppercase
type T = Uppercase<'string'>;
let a: T = 'STRING'
解析: 字符串转换为大写;
Lowercase
type T2 = Lowercase<'STRING'>;
let a2: T2 = 'string'
解析: 字符串转换为小写;
Capitalize
type T3 = Capitalize<'string'>;
let a3: T3 = 'String'
解析: 字符串首字母转换为大写;
Uncapitalize
type T4 = Uncapitalize<'STRING'>;
let a4: T4 = 'sTRING'
解析: 字符串首字母转换为小写;
至此关于类型转换方面的介绍就结束了。如果没有意外短期内不会再有关于TS的分享。不过我会抽出时间整合目前所分享的内容,并且做一些拓展和更详细的说明。致谢!