宠物网站页面设计简笔,深圳设计网站招聘,古色古香网站模板,电脑网站设计页面类型运算符
1. keyof运算符 1. 简介
是一个单目运算符#xff0c;接受一个对象类型作为参数#xff0c;返回该对象的所有键名组成的联合类型。
type MyObj {foo: number,bar: string,
};type Keys keyof MyObj; // foo|bar这个例子keyof MyObj返回MyObj的所有键名组成的…类型运算符
1. keyof运算符 1. 简介
是一个单目运算符接受一个对象类型作为参数返回该对象的所有键名组成的联合类型。
type MyObj {foo: number,bar: string,
};type Keys keyof MyObj; // foo|bar这个例子keyof MyObj返回MyObj的所有键名组成的联合类型即foo|bar
由于 JavaScript 对象的键名只有三种类型所以对于任意对象的键名的联合类型就是string|number|symbol。
对于没有自定义键名的类型使用 keyof 运算符返回never类型表示不可能有这样类型的键名
type KeyT keyof object; // never
上面示例中由于object类型没有自身的属性也就没有键名所以keyof object返回never类型。
由于 keyof 返回的类型是string|number|symbol如果有些场合只需要其中的一种类型那么可以采用交叉类型的写法。
type CapitalT extends string CapitalizeT;type MyKeysObj extends object Capitalkeyof Obj; // 报错
type MyKeysObj extends object Capitalstring keyof Obj;这个列子中string keyof Obj等同于string string|number|symbol进行交集运算最后返回string因此CapitalT extends string就不会报错了。
如果对象属性名采用索引形式keyof 会返回属性名的索引类型。
// 示例一
interface T {[prop: number]: number;
}// number
type KeyT keyof T;// 示例二
interface T {[prop: string]: number;
}// string|number
type KeyT keyof T;
上面的示例二keyof T返回的类型是string|number原因是 JavaScript 属性名为字符串时包含了属性名为数值的情况因为数值属性名会自动转为字符串
如果 keyof 运算符用于数组或元组类型得到的结果可能出人意料。
type Result keyof [a, b, c];
// 返回 number | 0 | 1 | 2
// | length | pop | push | ···上面示例中keyof 会返回数组的所有键名包括数字键名和继承的键名。
对于联合类型keyof 返回成员共有的键名。
type A { a: string; z: boolean };
type B { b: string; z: boolean };// 返回 z
type KeyT keyof (A | B);对于交叉类型keyof 返回所有键名。
type A { a: string; x: boolean };
type B { b: string; y: number };// 返回 a | x | b | y
type KeyT keyof (A B);// 相当于
keyof (A B) ≡ keyof A | keyof Bkeyof 取出的是键名组成的联合类型如果想取出键值组成的联合类型可以像下面这样写。
type MyObj {foo: number,bar: string,
};type Keys keyof MyObj;type Values MyObj[Keys]; // number|string
上面示例中Keys是键名组成的联合类型而MyObj[Keys]会取出每个键名对应的键值类型组成一个新的联合类型即number|string。 2. keyof运算符的用途
往往用于精确表达对象的属性类型用于属性映射即将一个类型的所有属性逐一映射成其他值 2. in运算符
在js中in用来确定对象是否包含某个属性名在ts 类型运算中in运算符用来取出遍历联合类型的每一个成员类型。
type U a|b|c;type Foo {[Prop in U]: number;
};
// 等同于
type Foo {a: number,b: number,c: number
};[Prop in U]表示依次取出联合类型U的每一个成员。 3. 方括号运算符
用来取出对象的键值类型比如T[K]会返回对象T的属性K的类型。
type Person {age: number;name: string;alive: boolean;
};
// Age 的类型是 number
type Age Person[age];方括号的参数如果是联合类型那么返回的也是联合类型。
type Person {age: number;name: string;alive: boolean;
};// number|string
type T Person[age|name];// number|string|boolean
type A Person[keyof Person];如果访问不存在的属性会报错。
type T Person[notExisted]; // 报错方括号运算符的参数也可以是属性名的索引类型。
type Obj {[key:string]: number,
};// number
type T Obj[string];这个语法对于数组也适用可以使用number作为方括号的参数。
// MyArray 的类型是 { [key:number]: string }
const MyArray [a,b,c];// 等同于 (typeof MyArray)[number]
// 返回 string
type Person typeof MyArray[number];上面示例中MyArray是一个数组它的类型实际上是属性名的数值索引而typeof MyArray[number]的typeof运算优先级高于方括号所以返回的是所有数值键名的键值类型string。
方括号里面不能有值的运算。
// 示例一
const key age;
type Age Person[key]; // 报错// 示例二
type Age Person[a g e]; // 报错
上面两个示例方括号里面都涉及值的运算编译时不会进行这种运算所以会报错。 4. extends…?:条件运算符
可以根据当前类型是否符合某种条件返回不同的类型。
T extends U ? X : Y上面式子中的extends用来判断类型T是否可以赋值给类型U即T是否为U的子类型这里的T和U可以是任意类型。如果T能够赋值给类型U表达式的结果为类型X否则结果为类型Y。
// true
type T 1 extends number ? true : false;上面示例中1是number的子类型所以返回true。
如果需要判断的类型是一个联合类型那么条件运算符会展开这个联合类型。
(A|B) extends U ? X : Y// 等同于(A extends U ? X : Y) |
(B extends U ? X : Y)上面示例中A|B是一个联合类型进行条件运算时相当于A和B分别进行运算符返回结果组成一个联合类型。
如果不希望联合类型被条件运算符展开可以把extends两侧的操作数都放在方括号里面。
// 示例一
type ToArrayType Type extends any ? Type[] : never;// string[]|number[]
type T ToArraystring|number;// 示例二
type ToArrayType [Type] extends [any] ? Type[] : never;// (string | number)[]
type T ToArraystring|number;
上面的示例一传入ToArrayType的类型参数是一个联合类型所以会被展开返回的也是联合类型。示例二是extends两侧的运算数都放在方括号里面所以传入的联合类型不会展开返回的是一个数组。
条件运算符还可以嵌套使用。
type LiteralTypeNameT T extends undefined ? undefined :T extends null ? null :T extends boolean ? boolean :T extends number ? number :T extends bigint ? bigint :T extends string ? string :never;// bigint
type Result1 LiteralTypeName123n;// string | number | boolean
type Result2 LiteralTypeNametrue | 1 | a;上面示例是一个多重判断返回一个字符串的值类型对应当前类型。 5. infer关键字
用来定义泛型里面推断出来的类型参数而不是外部传入的类型参数。它通常跟条件运算符一起使用用在extends关键字后面的父类型中。
type FlattenType Type extends Arrayinfer Item ? Item : Type;上面示例中infer Item表示Item这个参数是 TypeScript 自己推断出来的不用显式传入而FlattenType则表示Type这个类型参数是外部传入的。Type extends Arrayinfer Item则表示如果参数Type是一个数组那么就将该数组的成员类型推断为Item即Item是从Type推断出来的。
一旦使用Infer Item定义了Item后面的代码就可以直接调用Item了。下面是上例的泛型FlattenType的用法。
// string
type Str Flattenstring[];// number
type Num Flattennumber;
上面示例中第一个例子Flattenstring[]传入的类型参数是string[]可以推断出Item的类型是string所以返回的是string。第二个例子Flattennumber传入的类型参数是number它不是数组所以直接返回自身。
如果不用infer定义类型参数那么就要传入两个类型参数。
type FlattenType, Item Type extends ArrayItem ? Item : Type;
上面是不使用infer的写法每次调用Flatten的时候都要传入两个参数就比较麻烦。
下面的例子使用infer推断函数的参数类型和返回值类型。
type ReturnPromiseT T extends (...args: infer A) infer R ? (...args: A) PromiseR : T;
上面示例中如果T是函数就返回这个函数的 Promise 版本否则原样返回。infer A表示该函数的参数类型为Ainfer R表示该函数的返回值类型为R。
如果不使用infer就不得不把ReturnPromiseT写成ReturnPromiseT, A, R这样就很麻烦相当于开发者必须人肉推断编译器可以完成的工作。
下面是infer提取对象指定属性的例子。
type MyTypeT T extends {a: infer M,b: infer N} ? [M, N] : never;// 用法示例
type T MyType{ a: string; b: number };
// [string, number]
上面示例中infer提取了参数对象的属性a和属性b的类型。
下面是infer通过正则匹配提取类型参数的例子。
type Str foo-bar;type Bar Str extends foo-${infer rest} ? rest : never // bar
上面示例中rest是从模板字符串提取的类型参数。 6. is运算符
函数返回布尔值时可以使用is运算符来限定返回值与参数之间的关系。
is运算符用来描述返回值是true还是false。
function isFish(pet: Fish|Bird
):pet is Fish {return (pet as Fish).swim ! undefined;
}上面示例中函数isFish()的返回值类型为pet is Fish表示如果参数pet类型为Fish则返回true否则返回false。
is运算符总是用于描述函数的返回值类型写法采用parameterName is Type的形式即左侧为当前函数的参数名右侧为某一种类型。它返回一个布尔值表示左侧参数是否属于右侧的类型。
is运算符可以用于类型保护。
function isCat(a:any): a is Cat {return a.name kitty;
}let x:Cat|Dog;if (isCat(x)) {x.meow(); // 正确因为 x 肯定是 Cat 类型
}
上面示例中函数isCat()的返回类型是a is Cat它是一个布尔值。后面的if语句就用这个返回值进行判断从而起到类型保护的作用确保x是 Cat 类型从而x.meow()不会报错假定Cat类型拥有meow()方法
is运算符还有一种特殊用法就是用在类class的内部描述类的方法的返回值。
class Teacher {isStudent():this is Student {return false;}
}class Student {isStudent():this is Student {return true;}
}
上面示例中isStudent()方法的返回值类型取决于该方法内部的this是否为Student对象。如果是的就返回布尔值true否则返回false。
注意this is T这种写法只能用来描述方法的返回值类型而不能用来描述属性的类型。 7. 模板字符串
ts可以使用模板字符串构建类型模板字符串最大的特点就是内部可以引用其他类型。
type World world;// hello world
type Greeting hello ${World};上面示例中类型Greeting是一个模板字符串里面引用了另一个字符串类型world因此Greeting实际上是字符串hello world
模板字符串可以引用的类型一共6种分别是 string、number、bigint、boolean、null、undefined。引用这6种以外的类型会报错。
模板字符串里面引用的类型如果是一个联合类型那么它返回的也是一个联合类型即模板字符串可以展开联合类型。
type T A|B;// A_id|B_id
type U ${T}_id;上面示例中类型U是一个模板字符串里面引用了一个联合类型T导致最后得到的也是一个联合类型。
如果模板字符串引用两个联合类型它会交叉展开这两个类型。
type T A|B;type U 1|2;// A1|A2|B1|B2
type V ${T}${U};上面示例中T和U都是联合类型各自有两个成员模板字符串里面引用了这两个类型最后得到的就是一个4个成员的联合类型。 8. satisfies运算符
后期补