typescript和immutable js接口

时间:2017-09-18 16:27:45

标签: typescript immutable.js

我想为我的对象使用不可变的js,这是代码:

import {User} from "../../models/user";
import {Map} from "immutable";


    export interface State extends Map<string, any> {
      user: User,
      token: string,
    };

    const initialState: State = Map<string, any>({
      user: null,
      token: null,
    });

但我有这个错误:

Error:(11, 7) TS2322:Type 'Map<string, any>' is not assignable to type 'State'.
  Property 'user' is missing in type 'Map<string, any>'.

我该如何解决?

2 个答案:

答案 0 :(得分:2)

Map对象不包含usertoken属性,因此无法将其分配给State类型。因此,在使用Map时会丢失静态类型。

我强烈建议您使用Record而不是Map:

export interface IState {
    user: User,
    token: string,
}

export const State = Immutable.Record<IState>({
    user: null,
    token: null
});

const initialState = new State();
let state = initialState.set('token', '123');
let token = state.get('token');

不幸的是,来自Facebook的类型定义有点不对,但如果添加Readonly<T>声明,则只需阅读state.token属性:

export interface Instance<T extends Object> {
    ...
    set<K extends keyof T>(key: K, value: T[K]): this & Readonly<T>;
    update... : this & Readonly<T>;
    ...
}

More关于记录。

答案 1 :(得分:2)

我最近花了一些时间来解决这个问题。虽然我发现大多数答案建议切换到Records,但我正在做一个大型重构,并且不想更新相当大的代码库中的所有数据结构。

经过大量搜索,我发现这个github问题得到了我正在寻找的答案: https://github.com/facebook/immutable-js/issues/683#issuecomment-381089789(见最后评论。)

基本上,您扩展基本的immutable.Map接口以接受特定情况的类型定义。

对于您的具体情况,它看起来像这样:

import {User} from "../../models/user";
import {Map} from "immutable";

// The default Map interface accepts <K,V>: Key, Value.
// Build an interface that also accepts 'T': the shape of your data.
export interface IImmutableMap<T, K, V> extends Map<K, V> {
  toJS(): T;
  get<I extends keyof T>(key: I & K): T[I] & V;
  set<S extends keyof T>(key: S & K, value: T[S] & V): Map<K, V>;
}

// Extend Map to define the shape of your data
export interface IState extends Map<string, any> {
  user: User,
  token: string,
};

// Pass the shape to your new interface to define a type.
export type TState = IImmutableMap<IState, string, any>;

// Update the type definition on initial state to your type.
const initialState: TState = Map<string, any>({
  user: null,
  token: null,
});

您可以通过为每个特定案例创建新的接口和类型定义,在整个代码库中重用此IImutableMap接口。

如果您需要为其他immutable.js数据结构创建接口,那么不可变文档将是无价的:https://facebook.github.io/immutable-js/docs/#/

这是一个简短的博客,解释了为什么您可能选择不使用记录数据结构: https://blog.mayflower.de/6630-typescript-redux-immutablejs.html