Typescript中括号和keyof的几个特殊用法

痛定思痛。 2022-09-06 14:29 213阅读 0赞

1. 支持任意属性的接口

有时候我们希望一个接口允许有任意的属性,可以使用如下方式:

  1. interface Person {
  2. name: string;
  3. age?: number;
  4. [propName: string]: any;
  5. }
  6. let tom: Person = {
  7. name: 'Tom',
  8. gender: 'male'
  9. };

使用 [propName: string] 定义了任意属性取 string 类型的值。

需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集

  1. interface Person {
  2. name: string;
  3. age?: number;
  4. [propName: string]: string;
  5. }
  6. let tom: Person = {
  7. name: 'Tom',
  8. age: 25,
  9. gender: 'male'
  10. };
  11. // index.ts(3,5): error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
  12. // index.ts(7,5): error TS2322: Type '{ [x: string]: string | number; name: string; age: number; gender: string; }' is not assignable to type 'Person'.
  13. // Index signatures are incompatible.
  14. // Type 'string | number' is not assignable to type 'string'.
  15. // Type 'number' is not assignable to type 'string'.

上例中,任意属性的值允许是 string,但是可选属性 age 的值却是 number,number 不是 string 的子属性,所以报错了。

另外,在报错信息中可以看出,此时

  1. {
  2. name: 'Tom', age: 25, gender: 'male' }

的类型被推断成了

  1. {
  2. [x: string]: string | number; name: string; age: number; gender: string; },

这是联合类型和接口的结合。

一个接口中只能定义一个任意属性。如果接口中有多个类型的属性,则可以在任意属性中使用联合类型:

  1. interface Person {
  2. name: string;
  3. age?: number;
  4. [propName: string]: string | number;
  5. }
  6. let tom: Person = {
  7. name: 'Tom',
  8. age: 25,
  9. gender: 'male'
  10. };

2. 获取接口属性类型的联合值

  1. interface Student {
  2. name: string;
  3. age: number;
  4. }

这时如果我们对interface使用keyof

  1. type propKeys = keyof Student // name | age

我们知道输出的是以接口属性的键命组成的联合类型: ‘name’ | ‘age’
这时我们如果要获得各个键的属性所组成的联合类型,比如上面的string和number,可以这样做

  1. type propTypes = Student[keyof Student]

这里的propTypes就是个联合类型: string | number

3. in keyof 用法示例

  1. interface BrowserCache {
  2. TOKEN_CACHE: string;
  3. ID_CACHE: number;
  4. }
  5. type TCacheExpiretTime = {
  6. [key in keyof BrowserCache]: Date;
  7. }

TCacheExpireTime最终类型推断将会是

  1. type TCacheExpiretTime = {
  2. TOKEN_CACHE: Date | undefined;
  3. ID_CACHE: Date | undefined;
  4. }

如果想每个属性可选,可将代码修改成

  1. type TCacheExpiretTime = {
  2. [key in keyof BrowserCache]?: Date;
  3. }

TCacheExpireTime最终类型推断将会是

  1. type TCacheExpiretTime = {
  2. TOKEN_CACHE?: Date | undefined;
  3. ID_CACHE?: Date | undefined;
  4. }

《待续》今后碰到相关用法在这里记录下,充当笔记。

参考

  1. http://ts.xcatliu.com/basics/type-of-object-interfaces.html

发表评论

表情:
评论列表 (有 0 条评论,213人围观)

还没有评论,来说两句吧...

相关阅读