daxim
daxim

Reputation: 39158

How do you declare a value constrained type?

Ada

type Year_type is range 1800 .. 2100;

Raku

subset Natural of Int where * ≥ 0;

Kavorka

Int $even where { $_ % 2 == 0 }

TS

type Natural = BigInteger /* hypothetical → */ where (n) => { return n >= 0 };

Upvotes: 2

Views: 56

Answers (2)

C.Champagne
C.Champagne

Reputation: 5489

As far as I know, here isn't such a type of constraint or Range and one solution by be creating a specific class implementing those constrains.

In addition to this the union types may help you with smaller ranges:

type EvenDigits  = 0 | 2 | 4 | 6 | 8;

Upvotes: 1

jcalz
jcalz

Reputation: 328302

You can't, at least as of TS3.8.

There is an open suggestion, microsoft/TypeScript#15480 to support a ranged numeric type; if you want to see that happen you might want to go to that issue, give it a 👍, and maybe describe your use case if you think it's particularly compelling and not already accounted for.

For the "even number" type in one of your examples, you'd need something else entirely; probably as a prerequisite you'd need the compiler to be able to perform arithmetic at the type level, which it currently does not do. As usual, there's an existing open issue for that, microsoft/TypeScript#26382, but I don't know if that will ever seriously happen. Dependent types are great but I don't know if they will happen anytime soon in the language.

Until then the best you can do is make a nominal-like type and a user-defined type guard to allow values to be of the proper type. But all that's doing is forcing developers to perform a bunch of runtime tests every time they want to use your constrained type, since the compiler can't enforce or check it:

type EvenNumber = number & { ___isEven: true };

function isEven(x: number): x is EvenNumber {
  return x % 2 == 0;
}

function divideByTwoEvenly(x: EvenNumber): number {
  return x / 2;
}

const a = divideByTwoEvenly(100); // error! 100 is not an EvenNumber
const hundred = 100;
if (isEven(hundred)) {
  const a = divideByTwoEvenly(hundred);
} else {
  throw new Error("I'm SAD");
}

Not so great. Oh well, hope that helps; good luck!

Playground link to code

Upvotes: 2

Related Questions