使用条件属性/限制在typescript中定义类型

时间:2018-04-05 12:57:35

标签: typescript types

我是打字稿的新手,并学会了如何定义自定义类型,如:

  

输入T = {a:number,b:any}

是否可以使用类中定义的类型构造函数在TypeScript中为长度大于2的所有字符串集定义类型?

或者可能为所有大于0的数字的集合定义类型?

1 个答案:

答案 0 :(得分:6)

虽然您无法在编译时强制执行此类任意约束,但您可以创建强制用户调用执行这些验证的函数的类型,然后使用品牌类型依赖于代码中的这些不变量

type PositiveNumber =  number & { positive: true}
type StringOfMinLength<T extends number> =  string & { minLegth: T}

type T = {a:PositiveNumber, b:StringOfMinLength<3> }

function isPositiveNumber(value: number): value is PositiveNumber {
    if( value < 0 ) return false
    return  true;
}
function asPositiveNumber(value: number) {
    if( !isPositiveNumber(value) ) throw new Error("Not ok")
    return value; // type guard above, value will now be a PositiveNumber 
}

function isStringOfMinLength<T extends number>(value: string, length: T): value is StringOfMinLength<T> {
    if( value.length < length ) return false;
    return true;
}

function asStringOfMinLength<T extends number>(value: string, length: T): StringOfMinLength<T> {
    if(!isStringOfMinLength(value, length) ) throw new Error("Not ok")
    return value; // type guard above, value will now be a PositiveNumber 
}

type MyData = {a:PositiveNumber, b:StringOfMinLength<3>}
let myObj: MyData = {
    a: asPositiveNumber(0),
    b: asStringOfMinLength("Test", 3),
}

Math.sqrt(myObj.a) // a will be greater then 0
myObj.b[2] // index will exist, length greater then 3

let myNotOkObject: MyData = {
    a: -1, // will be a compile error, the checking function is not called
    b: "Test" // this will also be an error event though it satisfies the constraint since we don't call the appropriate function
}

// we can also use the type guard version instead (is*) of the assertion version (as*)
let a = 10;
let b = "Test"
if(isPositiveNumber(a) && isStringOfMinLength(b, 3))
{
    let myOtherObj: MyData = { a, b } // a and b are PositiveNumber and respectively StringOfMinLength<3>
} else {
    // handle case when they are not what was expected
}

您可以在需要基本类型的任何地方使用品牌类型(ex Math.sqrt(myObj.a)),但不能将基本类型直接分配给品牌类型的字段。这在实际代码中是否有价值取决于您和您的用例。

article对品牌类型进行了更多讨论。

修改

添加了品牌类型创建函数的类型保护版本,这样您就可以检查不变量是否为真并自行处理错误情况而不是抛出错误。 10x到@AluanHaddad的想法。