2017-04-25 49 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

相关问题