TypeScript 3.5:如何使用索引符號更新物件屬性?
在 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' 無法指派給類型 'never'。
我知道這種行為現在是有意的,並且是由 3.5 版本中引入的破壞性更改之一引起的:https://github.com/microsoft/TypeScript/wiki/Breaking-Changes#fixes-to-unsound-writes-to-indexed-access-types
但其中提到的變通方法對我不起作用——因為我有數百個不同類型屬性的對象。而且我也不想像那裡建議的那樣,為每組相同類型的屬性引入單獨的重置函數。
我也無法找到一個編譯器選項來啟用這個新行為。
我可以選擇使用之前的 TS 版本。但這顯然只是暫時的解決方案。
那有人能建議一個解決方法嗎?
答案#1
問題在於你的 name! 欄位是必填的(由非空斷言運算子 ! 所要求)。如果你將它改成 ?,則 Typescript 的錯誤就會消失。
之前:
之後:
class Test {
name?: string;
age?: number;
birthDate?: Date;
resetSomeField(this: Test, key: TestKey): void {
this[key] = undefined
}
...
在這裡玩它
答案#2
從技術層面來看這或許是錯誤的做法,但它實在太麻煩了,所以我還是採用了它:
(object[key] as any) = newVal;

