TypeScript 3.5:如何使用索引器符号更新对象属性?

时间:2019-08-01 09:37:22

标签: typescript

在TS 3.5之前,我能够做到:

type Nullable<T> = T | undefined;
type KeyOf<T> = Extract<keyof T, string>;
type ExcludeKey<T, K extends KeyOf<T>, E> = T[K] extends Nullable<E> ? never : K;
type ExtractKey<T, K extends KeyOf<T>, E> = T[K] extends Nullable<E>  ? K : never;
type NonFunctionPropertyNames<T> = { [K in KeyOf<T>]: ExcludeKey<T, K, Function>; }[KeyOf<T>];
type TestKey = NonFunctionPropertyNames<Test>;
type TestKeyList = TestKey[];

class Test {
  name!: string;
  age?: number;
  birthDate?: Date;

  resetSomeField(key: TestKey): void {
    this[key] = undefined;    
  }

  resetAllFields(): void {
    const keys = Object.keys(this) as TestKeyList;
    keys.forEach(this.resetSomeField);
  }
}

但是升级到3.5.3行之后

this[key] = undefined;

给我一​​个错误:

  

错误TS2322:类型'undefined'不能分配给类型'从不'。

我知道此行为是由3.5中引入的重大更改之一引起的: https://github.com/microsoft/TypeScript/wiki/Breaking-Changes#fixes-to-unsound-writes-to-indexed-access-types

但是其中提到的解决方法对我不起作用-因为我的对象具有数百个具有不同类型的属性。而且,我不想像那里建议的那样为每个相同类型的属性集引入单独的重置功能。<​​/ p>

我也找不到能够改变这种新行为的编译器选项。

(可选)我可以使用以前的TS版本。但这显然是一个临时解决方案。

那么有人可以建议解决方法吗?

1 个答案:

答案 0 :(得分:1)

问题是您的name!字段是必需的(非空断言运算符!)。如果将其更改为?,则Typescript错误就会消失。

之前:
before
之后:
after

class Test {
  name?: string;
  age?: number;
  birthDate?: Date;

  resetSomeField(this: Test, key: TestKey): void {
    this[key] = undefined
  }
...

Play with it here