首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用FlowType键入特定ID

使用FlowType键入特定ID
EN

Stack Overflow用户
提问于 2017-02-23 00:05:53
回答 1查看 109关注 0票数 2

我想要定义一个实体映射,这样键必须始终是某个指定类型的其他对象的ID。所需的用法如下:

代码语言:javascript
复制
export type Id<T> = {
  id: string
};

export type Foo = Id<Foo> & {
  val: number
};

// type Foo is now {id: Id<Foo>, val: number}

export type Bar = Id<Bar> & {
  val: number
};

// type Bar is now {id: Id<Bar>, val: number}

// FooMap should only be able to store objects of type foo, referenced by 
// IDs of type Id<Foo>
export type FooMap = {
  [key: Id<Foo>]: Foo
};

const foo1: Foo = { id: "foo1", val: 1 };
const foo2: Foo = { id: "foo2", val: 2 };
const bar1: Bar = { id: "bar1", val: 3 };

// This would pass type checking:
const fooMap: FooMap = {
  [foo1.id]: foo1,
  [foo2.id]: foo2
};

// But this would fail type checking:
const badMap: FooMap = {
  [bar1.id]: foo1
};

我的用例是,我希望有一个规范化的对象结构,通过ID管理关系。但是,由于ID都是相同的底层类型(例如,stringnumber),所以可能会意外地编写类似于上面的badMap示例的代码。我希望FlowType能够帮助防止这种情况的发生,因为我要求在以编程方式构造映射时只能引用正确的ID类型。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-07 21:57:15

从概念上讲,我认为您需要一个带有标记的联合类型来表示您正在使用的各种is -下面是F#:单一案件歧视工会中的一个例子。

如果我正确地理解了您,您希望创建像Map<FooId, Foo>这样的映射,其中fooMap[someFooId]只能包含一个Foo对象。但是,由于FooId可能是与BarId相同的类型,所以您可能在映射中有someBarId: Foo。你想要流向可能发生这种情况的打字机箱。

不幸的是,我不认为现在有一个简单的方法来做到这一点,因为它缺乏单一的案例标记的工会。在F#中,您可以这样做:

代码语言:javascript
复制
type FooId = FooId of string
type BarId = BarId of string

type Id<'T> = Id of 'T // you'd pass in FooId as the type

type Foo = {
    id: Id<FooId>;
    value: string;
}

type Bar = {
    id: Id<BarId>;
    value: string;
}

let foo: Foo = { id = Id (FooId "12345"); value = "fooVal" }
let bar: Bar = { id = Id (BarId "12345"); value = "barVal" }
let fooMap =
    Map.empty<Id<FooId>, Foo>
    |> Map.add (Id (BarId "12345")) foo

在JavaScript里我能得到的最接近的东西就是这样的东西。这方面的问题是类型错误发生在FooId/BarId的定义上。我们得到:

代码语言:javascript
复制
string literal `FooId`. Expected string literal `BarId`, got `FooId` instead
string literal `BarId`. Expected string literal `FooId`, got `BarId` instead

The JavaScript:

代码语言:javascript
复制
type FooId = "FooId";
type BarId = "BarId";
type Id<T> = {
  id: string;
  type: T
};

type Foo = {
  id: Id<FooId>, 
  val: any
};

type Bar = {
  id: Id<BarId>, // get type error here
  val: any
};

type FooMap = {
  [key: Id<FooId>]: Foo // get type error here
};

const fooIdBuilder = (id): Id<FooId> => ({ id, type: "FooId" });
const barIdBuilder = (id): Id<BarId> => ({ id, type: "BarId" });

const foo1: Foo = {
  id: fooIdBuilder("12345"),
  val: "fooval"
};

const foo2: Foo = {
  id: fooIdBuilder("23456"),
  val: "fooval"
};

const bar1: Bar = {
  id: barIdBuilder("23456"),
  val: "barval"
};

const fooMap: FooMap = {};
fooMap[foo1.id] = foo1;
fooMap[bar1.id] = foo2;

您可以复制并粘贴到试流中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42404668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档