Define type in typescript with conditional properties / limits

I am new to typescript and learned how to define a custom type, for example:

type T = {a: number, b: any}

Is it possible to define a type in typescript for a set of all strings longer than 2 using type constructors defined in the class?

or perhaps determine the type for the set of all numbers greater than 0?

+4
source share
1 answer

While you cannot impose such an arbitrary constraint at compile time, you can create types that force the user to call the functions that perform these checks, and then rely on these invariants in your code using the proprietary type

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)), . , .

.

Edit

​​ , , , , , . 10x @AluanHaddad .

+4

Source: https://habr.com/ru/post/1695813/


All Articles