How to declare a Map containing certain properties with flow

How to declare a Map containing certain properties with flowtype & immutable.js

本文关键字:certain properties with flow containing Map to declare How      更新时间:2023-09-26

给定一个像一样创建的网站对象

import {Map} from 'immutable' 
const website = new Map({name: 'My Website', url: 'http://www.myw.fr'})

我如何声明一个websiteType,它将是一个包含给定属性的映射。我知道我能做到:

declare type websiteType = Map<string,string>

但我希望更具体一些,并声明一个映射,该映射必须包含类型为string的属性nameurl

这可能吗?

希望我答对了你的问题,因为我从未使用过"不可变"中的映射,所以我将使用es6映射。

你为什么不使用一个类呢?

class Website extends Map<string, string> {
    constructor(name: string, url: string) {
        super()
        this.set("name", name)
        this.set("url", url)
    }
}

这样你就可以像这样初始化它:

const website = new Website("awesome", "www.awesome.com")

然后执行获取和设置操作。

如果您错过了参数,flowtype将抛出一个错误。

我希望这将是你的解决方案。

编辑:

您也可以创建一个函数来初始化您的映射。

declare type WebsiteType = Map<string, string>
function createWebsite(name: string, description: string) {
    const website: WebsiteType = new Map
    website.set("name", name)
    website.set("description", description)
    return website
}

然而,我发现第一个解决方案更好,因为它给你一个网站类型并且您不必创建创建者函数。

编辑:

如果您希望使用与地图初始化相同的语法,你也可以做:

class Website extends Map<string, string> {
    constructor({name, url, ...rest}) {
        super()
        this.set("name", name)
        this.set("url", url)
        for(const name in rest) {
            this.set(name, rest[name])
        }
    }
}

然而,我认为第一个有意义。

我不认为Map是这个问题的解决方案。您可以使用枚举来限制它,但这似乎并不能解决问题。以下是我玩游戏时得到的一些结果:

type MyKeys = 'A' | 'B';
declare type MyMapType = Map<MyKeys, number>;
const TinyMap: MyMapType = Map({
  A: 1,
});
// As expected this doesn't give an error
console.log(TinyMap.get('B'));
const MyMap: MyMapType = Map({
  A: 1,
  B: 2,
});
// Just a 'number'
MyMap.get('A');
// Somewhat surprisingly this works fine
const NewMap = MyMap.set('A', 'a');
// Now of type 'number | string'
NewMap.get('A')
// Forcing the return into the type causes the error that one
// perhaps would expect: 'string This type is incompatible with number'
const AnotherMap: MyMapType = MyMap.set('A', 'a');