为什么这在Typescript和Flow中有效?

时间:2017-09-15 16:05:19

标签: javascript typescript flowtype

基于Scott Wlaschin examples in F#, 我正在尝试使用Typescript设计功能域模型。

但是,为了为可选参数设置更严格定义的类型, 我注意到打字稿没有验证我预期的属性。

例如,对于这种类型:

type ObjectOne = {
    propertyOfOneMustBeNumber: number
}
type ObjectTwo = {
    propertyOfTwoMustBeNumber: number
}

type Options = ObjectOne | ObjectTwo

我有以下用例:

// valid
const test1: Options = {
    propertyOfOneMustBeNumber: 1,
    propertyOfTwoMustBeNumber: 2
}

// invalid:
// Object literal may only specify known properties,
// and 'unrecognized_property' does not exist in type 'Options'.
const test2: Options = {
    propertyOfOneMustBeNumber: 1,
    unrecognized_property: 'string'
}

// valid
const test3: Options = {
    propertyOfOneMustBeNumber: 1,
    propertyOfTwoMustBeNumber: 'string'
}

我理解为什么test2变量出错了, 但为什么test3变量没有错误, 即使propertyOfTwoMustBeNumber是字符串而不是数字?

这在Flow类型系统中也有效。

1 个答案:

答案 0 :(得分:1)

根据两种类型系统,test3ObjectOne的有效子类型。

在任何一种类型系统中,您都可以使用区分属性:

type ObjectOne = {
    kind: 'one';
    propertyOfOneMustBeNumber: number
}
type ObjectTwo = {
    kind: 'two';
    propertyOfTwoMustBeNumber: number
}

type Options = ObjectOne | ObjectTwo

// error
const test2: Options = {
    kind: 'one',
    propertyOfOneMustBeNumber: 1,
    unrecognized_property: 'string'
}

// error
const test3: Options = {
    kind: 'two',
    propertyOfOneMustBeNumber: 1,
    propertyOfTwoMustBeNumber: 'string'
}

在flowtype中,您还可以使用Exact Type,它将阻止现有的任何类型的额外属性:

type ObjectOne = {|
    propertyOfOneMustBeNumber: number
|}

在TypeScript中,您可以使用可选的never属性从对应类型中排除属性:

type ObjectOne = {
  propertyOfOneMustBeNumber: number;
  propertyOfTwoMustBeNumber?: never;
}
type ObjectTwo = {
  propertyOfOneMustBeNumber?: never;
  propertyOfTwoMustBeNumber: number;
}