在Flow中对子内置类型进行子类型化

Jos*_*osh 3 javascript flowtype

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

let foo: uuid = "Some string"
Run Code Online (Sandbox Code Playgroud)

但这应该成功:

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

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

type uuid = $Subtype<string>;
Run Code Online (Sandbox Code Playgroud)

但由于某种原因,它仍然允许从字符串赋值.

gca*_*nti 6

有以下黑客(缺点是a 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 :(
Run Code Online (Sandbox Code Playgroud)