2016-04-26 129 views
3

比方說,我有一個接口:Typescript是否支持「子集類型」?

interface IUser { 
    email: string; 
    id: number; 
    phone: string; 
}; 

然後我有期望類型的子集(或完全匹配)的功能。也許它會傳遞一個完整的對象,使它只會通過{email: "[email protected]"}。我希望類型檢查器允許這兩個。

例子:

function updateUser(user: IUser) { 
    // Update a "subset" of user attributes: 
    $http.put("https://stackoverflow.com/users/update", user); 
} 

不打字稿支持這樣的行爲嗎?我可以發現它非常有用,特別是像Redux這樣的範例。

爲了澄清,我們的目標是:

  1. 避免重新編寫界面和所有屬性手動設置爲可選。
  2. 避免分配意外的屬性(如拼寫錯誤)。
  3. 避免使用命令邏輯,如if語句,這會喪失編譯時類型檢查的好處。

UPDATE:打字稿已經宣佈mapped types支持,要解決這個問題一旦公佈。

+0

不是'Partial'你正在尋找? –

+0

當我問這個問題時,他們不存在。之後,我在添加到TS後添加了一個鏈接。 – Rick

回答

6

打字稿現在支持部分機型。

正確的方法來創建一個局部類型:

type PartialUser = Partial<IUser>;

1

您可以聲明一些或全部字段爲可選字段。

interface IUser { 
    email: string; // not optional 
    id?: number; // optional 
    phone?: string; // optional 
}; 
+0

這很接近,但不是我想要的。在IUser的情況下,所有字段都是強制性的。只是在某些情況下,我希望它是部分匹配。 – Rick

+0

的要求是矛盾的,你不能有一個領域是可選的和強制性的同時。 :P我想你可以使用2個接口來獲得這個.. – toskv

+1

有很多時候你會希望這個和其他語言(如Flow)允許它。這是爲了DRYness,你想在某些情況下允許一個子集。考慮骨幹模型更新,其中您命名的參數必須是模型屬性的子集。 – Rick

1

可以單獨成不同的接口:

interface IUser { 
    id: number; 
}; 

interface IUserEmail extends IUser { 
    email: string; 
} 

interface IUserPhone extends IUser { 
    phone: string; 
} 

有你的方法獲得基本IUser接口,然後檢查所需的字段:

function doit(user: IUser) { 
    if (user.email) { 

    } else if (user.phone) { 

    } 
} 
1

如果我正確理解這個問題,你想要像Flow的$Shape

所以,在一個地方,你可能有一些需要類型

interface IUser { 
    email: string; 
    id: number; 
    phone: string; 
}; 

然後,在另一個地方,你想用同一類型的IUSER類型只是現在所有可選字段。

interface IUserOptional { 
    email?: string; 
    id?: number; 
    phone?: string; 
}; 

您想根據IUserIUserOptional的方式自動生成,而無需再次寫出來的類型。

現在,我不認爲這是可能的Typescript。事情可能在2.0版本中發生變化,但我認爲我們甚至沒有在Typescript中接近這樣的東西。

你可以看看一個預編譯器,它可以在打字稿運行之前爲你生成這樣的代碼,但這聽起來不是一件微不足道的事情。

考慮到這個問題,我只能建議你嘗試使用Flow。在流程中,您只需執行$Shape<IUser>即可生成您想要編程的類型。當然,Flow在許多大小方面與Typescript不同,所以請牢記這一點。流量是不是一個編譯器,這樣你就不會得到像枚舉和類實現interfactes

0

與映射類型妥善的解決辦法:

updateUser<K extends keyof IUser>(userData: {[P in K]: IUser[P]}) { 
    ... 
}