打字稿|不变的扩展Immutable.Map类型的正确方法 [英] TypeScript | Immutable | proper way of extending Immutable.Map type

查看:85
本文介绍了打字稿|不变的扩展Immutable.Map类型的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用不可变包用打字稿写的react-redux应用程序.那里有一个数据,这些数据来自api,在存储区中,我将其打包到Map中.在所有应用程序中,它们都用作地图.

I have a react-redux application written in typescript with immutable package. There I have a data, which comes from api and in store I pack it to Map. In all application they are used as a Map.

我创建了一个界面:

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

总体来说,它的效果非常好.除了测试外,我是通过这种方式创建数据的:

In general it works very good. Except tests, where I create data this way:

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

然后出现一个皮棉错误:

and then I get a lint error:

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.

I feel totally lost, as I can see id in interface and in my dummy data.

我希望能对此有所启发.我觉得我应该以某种方式将可接受的密钥列表传递给我的地图,但是不知道如何执行此操作.

I would appreciate some light on it. I feel that somehow I should pass the list of acceptable keys to my Map, but no idea, how to do this.

拼写错误

推荐答案

我们在项目中使用了这种方法(略有不同的方法):

We used it like this in our project (slightly different approach):

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

我们使用了Immutable.js类型的较旧版本,但尚未使用映射类型(T[K]).此后,将更新AFAIK的类型,并且无需覆盖get方法.

We used an older version of the Immutable.js typings that didn't used mapped types yet (T[K]). AFAIK typings are updated since then and there is no need to overwrite the get method.

实际上,与上面的方法不同,实际上get方法仍然不是完全安全的类型.因此,覆盖该方法仍然有其优点.

Actually the get method still is not fully type safe unlike the above. So overwriting the method still has its merits.

使用上面的声明,您可以创建不可变的地图,例如:

With the above declaration you can then create immutable maps like:

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

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


理想情况下,您希望输入以下内容:


Ideally, you would like typings like this:

/**
 * 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`

为了通过Immutable.js实现上述目的,您可以创建一个小的辅助函数,其唯一目的是修复"键入内容:

In order to achieve the above with Immutable.js you can create a small helper function, whose only purpose is to "fix" typings:

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.与Map相比,使用fromJS的好处是键入更容易被覆盖.

Note that I used fromJS in the example. This will create a Map as long as the passed input is an Object. The benefit of using fromJS over Map is that the typings are easier to overwrite.

旁注:您可能还想研究Record s.

Side note: You might also want to look into Records.

这篇关于打字稿|不变的扩展Immutable.Map类型的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆