0

Typescript derive union type from tuple/array values

is very informative.

const list = ['a', 'b', 'c'] as const; // TS3.4 syntax
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';

Now, I try to make a type of Integer that has a range(0...255).

For an initial test, when [0,1,2,3] is manually prepared, it works as expected.

  const int3 = [0, 1, 2, 3] as const;
  type Int3 = typeof int3[number];
  //  0 | 1 | 2 | 3
  const a: Int3 = 3; //ok, but error on >=4

However, when [0,1,..,255] is prepaired with Array.keys() iteration, it won't work...

  const int255 = [...Array(255).keys()] as const; // [0,1,..,255]
  type Int255 = typeof int255[number];
  const colorCode: Int255 = 300; //ok to compile,should be error

Is there any fix on this? Thanks.

Related topic here:

Is it possible to restrict number to a certain range

is not answered to question and it's TypeScript2.0 age(more than 5 years ago)

SmoothTraderKen
  • 602
  • 4
  • 16
  • 2
    `int255` is of `number[]` type. Because `Array#keys` returns `number[]`. `as const` only makes sense with constant literals. You need to put all the values explicitly, so that they've been known compile-time. – zerkms Oct 01 '20 at 20:59
  • Thanks, looks like so, but `as const` is literally to make sense as constant literals. Do you know how to put all the values explicitly? – SmoothTraderKen Oct 01 '20 at 21:04
  • "Do you know how to put all the values explicitly?" --- yep, just type them one after another: `[0, 1, 2, 4, 5, 6, 7` and so on and so forth. "is literally to make sense as constant literals" --- that's right, and your one is not: its value is determined in runtime. – zerkms Oct 01 '20 at 21:05
  • 1
    @zerkms Obviously, that's not the solution. and I don't think `[...Array(255).keys()] ` need to be determined in runtime. – SmoothTraderKen Oct 01 '20 at 21:06
  • 1
    "I don't think ... need to be determined in runtime" --- all functions need to be executed in runtime to obtain their results. – zerkms Oct 01 '20 at 21:10
  • 1
    If you don't accept writing all numbers explicitly as a solution then the answer to your question is "there is no solution". – Ingo Bürk Oct 01 '20 at 21:12
  • @zerkms Then how typescript type system can infer the return value of various functions without execution? – SmoothTraderKen Oct 01 '20 at 21:12
  • @smithK return type is a part of function signature (if it's not declared explicitly - it would statically analyse it). Function's signature is known compile time. To obtain returned value though you must evaluate the function. – zerkms Oct 01 '20 at 21:13
  • @IngoBürk Just to make sure it's not my personal matter, and I suppose most programmers won't accept the issue. – SmoothTraderKen Oct 01 '20 at 21:14
  • 1
    It has flow analysis of functions, but that analysis is limited both for complexity and performance reasons. Your example is something it will not be able to infer because it doesn't just require analysing the function but doing so with specific knowledge on the object on which it is called. – Ingo Bürk Oct 01 '20 at 21:15
  • For the record, what you're looking to do is an open feature request: https://github.com/microsoft/TypeScript/issues/15480 – Ingo Bürk Oct 01 '20 at 21:17
  • @IngoBürk Ok, fine, then it's not the matter of "phase of runtime" but the matter of "limitation for complexity and performance". – SmoothTraderKen Oct 01 '20 at 21:18
  • "it's not the matter of "phase of runtime"", "but the matter of "limitation for complexity and performance"" --- it's exactly the same: if you had unlimited computation resources and time to implement it, you could put as much runtime (eager evaluation) into TSC (compile time) as possible. – zerkms Oct 01 '20 at 21:20
  • 1
    @zerkms No, it's not same at all, you said " and your one is not: its value is determined in runtime" and if it's really the principle, it would be impossible. I know it's not principle but the computation resources and time. Please do not mix-in such a thing here. – SmoothTraderKen Oct 01 '20 at 21:23
  • @ford04 In fact, `[...Array(255).keys()] ` is the generator. – SmoothTraderKen Oct 01 '20 at 21:35
  • 1
    @smithK `[...Array(255).keys()]` is a *value* generator, not a *type* one. As said, `Array.keys()` cannot provide numeric literal types. – ford04 Oct 01 '20 at 21:37
  • 2
    Voting to close as duplicate of [Is it possible to restrict number to a certain range](https://stackoverflow.com/questions/39494689/is-it-possible-to-restrict-number-to-a-certain-range) – Ingo Bürk Oct 01 '20 at 22:07

2 Answers2

2

To sum up a lengthy discussion in the comments: at the time of writing this is not (practically) possible unless you explicitly write out all individual numbers. And even then it's fairly limited.

There is, however, an open feature request for this which can be found here: https://github.com/microsoft/TypeScript/issues/15480

Ingo Bürk
  • 19,263
  • 6
  • 66
  • 100
-1

Is there any fix on this?

No, not at the moment.

zerkms
  • 249,484
  • 69
  • 436
  • 539
  • 1
    This is logically correct, and you keep avoiding to mention this with mentioning as if my code is inappropriate or inference limitation of runtime determination. The fact is simply ability of TypeScript. Knowing this you have kept to avoid to admit that. Now better. – SmoothTraderKen Oct 01 '20 at 22:04
  • 1
    @smithK I answered the very and the only question you asked. If you really wanted to ask something else - you should have done it explicitly. "Knowing this you have kept to avoid to admit that" --- this statement makes no sense, sorry. – zerkms Oct 01 '20 at 22:07
  • 1
    It's not something else. The topic is identical, and here is a place that users can provide alternative solutions. Writing from 0...255 is obviously not the solution the most programmers will never accept. – SmoothTraderKen Oct 01 '20 at 22:11
  • 1
    As a programmer unwilling to accept a missing feature you have the obvious solution of contributing to TS or forking it, but neither of those are reasonable answers in the scope of an SO question. – Ingo Bürk Oct 01 '20 at 22:17
  • 1
    @IngoBürk That comment is also out of scope here. Why you want to comment those? The only informative fact you provided is the feature request URL. Why can't you guys concisely answer "currently not available, but there is a feature request: URL"?? – SmoothTraderKen Oct 01 '20 at 22:30
  • 1
    I did. You called it "incorrect" and said you didn't "accept" it. – Ingo Bürk Oct 01 '20 at 22:31
  • 1
    @smithK "Why can't you guys concisely answer" --- are you sure you've read the Ingo's answer? It **literally** says: "at the time of writing this is not (practically) possible" and it **literally** provides a feature request url. – zerkms Oct 01 '20 at 22:38