在Flow

时间:2016-11-12 01:52:51

标签: javascript flowtype

假设我正在编写处理UUID的代码。在内部,我想将它们表示为字符串。也就是说,每个UUID都是一个字符串,但不是每个字符串都是有效的UUID,并且我不想意外地将错误的东西分配给一个用于保存UUID的变量。所以我想创建一个类型' uuid'这样的分配就会失败:

let foo: uuid = "Some string"

但这应该成功:

function create_uuid(): uuid; { /* implementation? */ }
let foo: uuid = create_uuid(); 
let bar: string = uuid;  // this is fine

有没有办法用Flow创建具有这些属性的类型?我在研究中发现$Subtype,并认为这可行:

type uuid = $Subtype<string>;

但由于某种原因,它仍允许从字符串中进行分配。

3 个答案:

答案 0 :(得分:6)

存在以下黑客攻击(缺点是UUID也将是Object):

// keep this constructor private
class IsUUID {}

export type UUID = string & IsUUID;

export function create(): UUID {
  const uuid = 'blah' // <= your implementation
  return ((uuid: any): UUID)
}

// tests

declare function f(uuid: UUID): void;
declare function g(s: string): void;
declare function h(o: Object): void;

let foo = create()
let bar: string = foo // <= ok
f(foo) // <= ok
f(bar) // <= error: string. This type is incompatible with IsUUID
g(foo) // <= ok
g(bar) // <= ok
h(foo) // <= ok :(

答案 1 :(得分:4)

编辑:这个答案已经过时了。自从提出这个问题以来,Flow已经实现了不透明类型。请参阅ESRogs&#39;答案。

可能有一些黑客可以解决这个问题,但你所要求的是opaque data type,而Flow目前不支持它们。以下是GitHub上Flow存储库中的some discussions

答案 2 :(得分:2)

使用带有子类型约束的不透明类型。从文档中:

exports.js

export opaque type ID: string = string;

imports.js

import type {ID} from './exports';

function formatID(x: ID): string {
    return "ID: " + x; // Ok! IDs are strings.
}

function toID(x: string): ID {
    return x; // Error: strings are not IDs.
}

https://flow.org/en/docs/types/opaque-types/