2017-04-25 95 views
1

我有一個react-redux應用程序,使用不可變包裝在typescript中編寫。在那裏我有一個數據,它來自api,並且在商店中我將它包裝到Map中。在所有應用程序中,它們都被用作Map。TypeScript |不可變|適當的方式來擴展Immutable.Map類型

我創建了一個接口:

export interface PaymentMethod extends Immutable.Map<string, string | NamedType<number>> { 
    id: string; 
    name: string; 
    description: string; 
    accountNr: string; 
    paymentMethodType: NamedType<number>; 
} 

一般來說它的作品非常好。除了測試,在那裏我創建的數據是這樣的:

const dummyPaymentMethod: PaymentMethod = Map({ 
    id: '', 
    name: '', 
    description: '', 
    accountNr: '', 
    paymentMethodType: { id: 1, name: '' }, 
}); 

,然後我得到一個皮棉錯誤:

Error:(116, 13) TS2322:Type 'Map<string, string | { id: number; name: string; }>' is not assignable to type 'PaymentMethod'. 
Property 'id' is missing in type 'Map<string, string | { id: number; name: string; }>'. 

我覺得完全失去了,因爲我可以在界面和我的虛擬數據看ID。

我會欣賞一些光。我覺得不知何故,我應該通過可接受的鍵列表到我的地圖,但不知道,如何做到這一點。

編輯:拼錯

回答

4

我們使用它像這樣在我們的項目(稍有不同的方法):

interface ImmutableMap<T> extends Map<string, any> { 
    get<K extends keyof T>(name: K): T[K]; 
} 

我們使用未使用的映射類型Immutable.js分型的舊版本,但( T[K])。 AFAIK類型自此更新並且不需要覆蓋get方法。

編輯:其實get方法仍然不是完全類型安全不同於上述。所以重寫該方法仍然有其優點。

有了上面的聲明,那麼你可以創建不可改變的地圖,如:

type AuthState = ImmutableMap<{ 
    user:string|null; 
    loggedIn:boolean; 
}>; 

const authState:AuthState = fromJS({ user: 'Alice', loggedIn: true }); 

理想情況下,你想分型如下:

/** 
* Imaging these are typings for your favorite immutable 
* library. We used it to enhance typings of `immutable.js` 
* with the latest TypeScript features. 
*/ 
declare function Immutable<T>(o: T): Immutable<T>; 
interface Immutable<T> { 
    get<K extends keyof T>(name: K): T[K]; 
    set<S>(o: S): Immutable<T & S>; 
} 

const alice = Immutable({ name: 'Alice', age: 29 }); 
alice.get('name');  // Ok, returns a `string` 
alice.get('age');  // Ok, returns a `number` 
alice.get('lastName'); // Error: Argument of type '"lastName"' is not assignable to parameter of type '"name" | "age"'. 

const aliceSmith = alice.set({ lastName: 'Smith' }); 
aliceSmith.get('name');  // Ok, returns a `string` 
aliceSmith.get('age');  // Ok, returns a `number` 
aliceSmith.get('lastName'); // Ok, returns `string` 

Link to the Playground


爲了實現上述與Immutable.js你可以創建一個小的輔助函數,其唯一目的是「修復」分型:

import { fromJS } from 'immutable'; 

interface Immutable<T> { 
    get<K extends keyof T>(name: K): T[K]; 
    set<S>(o: S): Immutable<T & S>; 
} 

function createImmutable<T extends object> (o:T) { 
    return fromJS(o) as Immutable<T>; 
} 

注意,我在示例中使用fromJS。只要通過的輸入是Object,這將創建Map。使用fromJS優於Map的好處是,類型更容易覆蓋。你可能還想看看Record s。

+1

謝謝,我從你的答案中得到了非常有用的信息。 – Kania

+0

這是否適用於'Record'(只帶'get')? – ton