2017-06-19 69 views
2

我有一個功能,讓我說,應該符合一個Person接口夾具:打字稿中使用部分類型覆蓋2.4

interface Person { 
    name: string 
    email: string 
    age?: number 
} 

function makePerson(override: Partial<Person> = {}): Person { 
    return { 
    name: 'Jim', 
    email: '[email protected], 
    age: 24, 
    ...override, 
    } 
} 

在打字稿2.3,這將很好地工作;我可以調用函數像這樣覆蓋某個鍵:它爲什麼做

Type '{ name: string | undefined; email: string | undefined; age: number | undefined; }' is not assignable to type 'Person'. 
    Types of property 'name' are incompatible. 
    Type 'string | undefined' is not assignable to type 'string'. 
     Type 'undefined' is not assignable to type 'string'. 

我可以看到:

const myPerson = makePerson({name: 'Bob'}) 
// { 
// name: 'Bob', 
// email: '[email protected], 
// age: 24, 
// } 

但是,已經更新到2.4,編譯器現在提供了這樣的錯誤這在JavaScript中可以通過傳入一個或多個鍵設置爲undefined的對象來覆蓋對象中的任何鍵,這些鍵將覆蓋默認值並導致函數返回不符合Person的對象。這是因爲省略密鑰與設置undefined不同。

有沒有辦法實現以前的工作,同時保持最大的安全類型?

+0

也許'Overwrite'可以幫助您,請參閱[#12215](https://github.com/Microsoft/TypeScript/issues/12215),以便通過nirendy和ahejlsberg實現。 – Tycho

+0

這看起來像一個很好的功能建議,但我不認爲它解決了這個問題。問題在於TS2.4對其「Partial」的實現更加嚴格,以及它如何解釋未定義,這可能是遺漏了實際設置爲「未定義」的密鑰或密鑰。 2.3不那麼挑剔,並且假定如果覆蓋中的鍵是'未定義的',它將被忽略,並且不會覆蓋默認值。 – harryg

+0

對不起,我現在看到。我現在可以通過禁用'strictNullChecks'來完成它的工作。可能不是理想的,但它是一些東西。幸運的是,「覆蓋」不再是功能請求;如果你添加一個定義它的作品。 :) – Tycho

回答

2

這可能不是最好的答案,但你可以通過避免對象傳播和設置每個單獨的字段來避開它。

function makePerson(override: Partial<Person> = {}): Person { 
    return { 
    name: override.name !== undefined ? override.name : 'Jim', 
    email: override.email !== undefined ? override.email : '[email protected]', 
    age: override.age !== undefined ? override.age : 24 
    } 
} 
+0

是的,我想這是一個選項。也許可以定義一個'applyOverrides'函數,它需要一個泛型來執行此操作。但不理想。 – harryg

0

這個答案至少看起來像只有理論 - 但它的工作原理。

將該類型視爲一組屬性,並且您希望能夠使用這些屬性的任何給定子集調用makePerson - 所有屬性的功率集。該類型可以表示爲:

type Person_Powerset = 
    {} | 
    {email: string} | { name: string } | { age: number} | 
    {name: string, email: string} | {name: string, age: number} | {email: string, age: number} | 
    {name: string, email: string, age: number}; 

我不知道是否打字稿是在類型級別足夠的表現力,讓建設這種類型的,例如如Powerset<Person>