【问题标题】:typescript and immutable js interface打字稿和不可变的js接口
【发布时间】:2018-02-27 06:37:56
【问题描述】:

我想为我的对象使用不可变的 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>'.

我该如何解决?

【问题讨论】:

    标签: typescript immutable.js


    【解决方案1】:

    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&lt;T&gt; 声明,你可以阅读 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关于记录。

    【讨论】:

      【解决方案2】:

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

      经过大量搜索,我发现这个 github issue 有我正在寻找的答案: 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/#/

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-02
        • 1970-01-01
        • 1970-01-01
        • 2022-11-23
        • 2017-09-26
        • 2019-06-12
        • 2019-06-01
        • 2016-04-04
        相关资源
        最近更新 更多