![](/img/trans.png)
[英]Typescript Why type guard does not work as expected for array of objects of type null-able union(strictNullChecks enabled)
[英]TypeScript union type on class property does not work as expected
我正在嘗試為我們的模型類正確鍵入一個屬性包裝器,然后該屬性獲取一個代理設置器,該設置器被支持接受原始的、已解析的值和包裝器實例本身。 它本身的代碼已經可以工作,只是導致問題的輸入。 這個問題最好用代碼來解釋。
屬性包裝器
abstract class BaseProp {}
type RawType = `/${string}/${number}` | null;
type ValType<M> = M | null | undefined;
type ResolvableProxy<M> = NonNullable<Resolvable<M> | RawType | ValType<M>>
class Resolvable<M> extends BaseProp {
raw!: RawType;
val!: ValType<M>;
// has internal logic to resolve how to assign which is called via a proxy
constructor (model: M) { super(); }
resolve () { return this; }
}
模型定義
class ModelA {
name!: string;
}
class ModelB {
a: ResolvableProxy<ModelA> = new Resolvable(ModelA);
// the proxy handles properties that are extended from BaseProp
// constructor () { return new Proxy(); }
}
這些模型被包裝到一個代理中,該代理對擴展BaseProp
的所有內容都有特殊處理,我沒有包括那部分代碼,因為我認為它在這里不相關。 代理按預期工作,只有鍵入會導致問題。
測試用法
let test1: ResolvableProxy<ModelA> = new Resolvable(ModelA);
test1.resolve(); // accessable
const test1Name = test1.val!.name; // accessable
test1.raw = '/path/1'; // accessable
test1.val = new ModelA(); // accessable
test1 = '/path/1';
test1 = new ModelA();
test1 = new Resolvable(ModelA);
預期用途
當在類屬性上使用時,聯合類型的行為不同,對我來說沒有意義。
let test2 = new ModelB();
test2.a.resolve(); // not accessable, why?
test2.a.raw = '/path/1'; // not accessable, why?
test2.a.val = new ModelA(); // not accessable, why?
test2.a = '/path/1';
test2.a = new ModelA();
test2.a = new Resolvable(ModelA);
使用“as”允許訪問 Resolvable 成員,但這將需要重寫大量代碼,這不是必需的,因為類型本身應該是正確的 IMO。 當循環類似數組的結構時,它也會變得過於復雜。
(test2.a as Resolvable<ModelA>).raw = '/path/1';
const test3 = (test2.a as Resolvable<ModelA>).val;
(test2.a as Resolvable<ModelA>).resolve();
我考慮過為每個屬性使用顯式 getter/setter,但這會帶來其他問題,例如“a”不是 json 字符串化格式,至少在沒有額外處理的情況下是這樣。
export class ModelC {
// @ts-ignore
#a: Resolvable<ModelA> = new Resolvable(ModelA);
get a(): Resolvable<ModelA> { return this.#a; }
set a(v: ResolvableProxy<ModelA>) { this.#a = v as any; }
}
const test4 = new ModelC();
test4.a.resolve();
test4.a.raw = '/path/1';
test4.a.val = new ModelA();
test4.a = '/path/1';
test4.a = new ModelA();
test4.a = new Resolvable(ModelA);
它在第一次測試中沒有出錯,因為它的類型被類型檢查器減少了
如果您破壞代碼塊,它將出錯
function testUsage() {
let test1: ResolvableProxy<ModelA> = new Resolvable(ModelA);
function f() {
test1.resolve(); // error
const test1Name = test1.val!.name; // error
test1.raw = '/path/1'; // error
test1.val = new ModelA(); // error
test1 = '/path/1';
test1 = new ModelA();
test1 = new Resolvable(ModelA);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.