2017-01-09 122 views
2

如果我有類自動初始化成員字段字符串文本類型的打字稿

class Foo { 
    type: "foo" 
    constructor(public id: number) {} 
} 

class Bar { 
    type: "bar" 
    constructor(public id: number) {} 
} 

type SomeUnion = Foo | Bar // (x : SomeUnion).type will have the type "foo" | "bar" 

建設的new Foo(1)實例將產生{ id: 1 }在運行時,但我想獲得{ id: 1, type: "foo" }

一個簡單的解決方案當然是鍵入字符串常量兩次,通過在構造函數中指定它,例如this.type = "class_name"

但是,這是非理想的,因爲我需要輸入相同的字符串常量兩次。這不是一個大問題,但這是人們可以忘記並導致錯誤的東西。

有沒有辦法自動創建與字符串文字具有相同值的對象的成員?

+0

您希望字段類型都是''class_name「'*和*類型的初始值''class_name」'。我問,因爲我不是100%確定你不只是混淆了類型聲明和字段初始化。 (並且你得到的答案將類型設置爲'string'。) – Louis

+0

是的,重要的是該類型是字符串文本,而不是通用的'string',以便將其用於程序中其他位置的聯合類型。 – Advecticity

回答

2

讓我們專注於這個代碼:

class Foo { 
    type: "foo" 
    constructor(public id: number) {} 
} 

如果編譯器選項strictNullChecksfalse,然後type: "foo"也隱含地允許設置type的價值觀undefinednull。我希望明確地將字段明確初始化爲undefined以外的值。


所以讓我們繼續與strictNullChecks設置爲true。在這種情況下,唯一可以分配給type的值是"foo"。它看起來像你希望什麼有一些辦法讓編譯器執行以下推理:

type: "foo"說評爲type領域必須是"foo"類型。因此,只能將值"foo"分配給它。因此,我應該發出代碼來自動將其初始化爲"foo",因爲沒有其他值可以分配給它。

問題在於TypeScript 2。x即使strictNullChecks當前也允許字段以值undefined開頭,即使分配undefined無效。讓我把這個明確:即使你不能分配undefinedtype,現場type可以與價值undefined(如果你不初始化)開始。這不被視爲錯誤。這就是TypeScript目前的設計。有一個issue report about this,有些人認爲這是該語言的設計缺陷。

無論如何,編譯器不會執行上述所需的推理。 現在,無論如何,您必須重複相同的值作爲字符串文字類型的一部分,並作爲您的type字段初始化的一部分。

0

怎麼辦?

class Foo { 
    type: string; 
    constructor(public id: number) { 
     this.type = "class_name"; 
    } 
} 
+1

如果這個類型是一個通用字符串,那麼你不能擁有諸如字符串文字的聯合類型之類的東西。 – Advecticity

1

如果「是很重要的類型是一個字符串文字,而不是爲了使用它在其他程序中的聯合類型的一般串」,那麼你應該有該聯盟類型,比方說:

type MyType = "foo" | "bar"; 

然後:

class Foo { 
    type: MyType = "foo"; 
    constructor(public id: number) {} 
} 

class Bar { 
    type: MyType = "bar"; 
    constructor(public id: number) {} 
} 

你也可以有一個共同的基類:

class Base 
    type: MyType; 
    protected constructor(type: MyType) { 
    this.type = type; 
    } 
} 

class Foo extends Base { 
    constructor(public id: number) { 
    super("foo"); 
    } 
} 

class Bar extends Base { 
    constructor(public id: number) { 
    super("bar"); 
    } 
} 
3

我認爲這將做你想要做的事情。您仍然必須輸入字符串文字兩次,但是它們的輸出非常接近,所以如果類類型更改爲更新這兩個值,您將不太可能會忘記。

class Foo { 
    type: "foo" = "foo" 
    constructor(public id: number) {} 
} 

class Bar { 
    type: "bar" = "bar" 
    constructor(public id: number) {} 
} 
+1

儘可能簡潔。 – Advecticity