Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
496 views
in Technique[技术] by (71.8m points)

javascript - Trying to understand index signatures in TypeScript

I think I basically got how index signatures work in TypeScript. However, there is one thing I don't get. Given the following sample code:

const sales: {[ key: string ]: number } = {
  a: 532,
  b: 798,
  c: 264
};

console.log(sales.a);
console.log(sales.d);

Now the compiler says, sales.a and sales.d are of type number. But shouldn't that be number | undefined, since the compiler can not know if a and / or d are actually there?

I can't come up with a specific interface here, because a and d are arbitrarily chosen at runtime, and not predefined.

I can solve this by using

{[ key: string ]: number | undefined }

as a type, but this seems to be cumbersome and annoying (and a pretty lame solution for a pretty trivial problem, given how objects are typically used in JavaScript).

So, one could say: To me, this seems counterintuitive: What sense do index signatures have, if they virtually enforce that for every possible string on earth there is also a value? For which type is this ever true?

Is there actually no easier solution for this than to come up with a

{[ …: string ]: … | undefined }

type over and over again? Nothing integrated into the language?

It's hard to believe that, given the fact that there are specialties such as Partial<T> and co. … any thoughts on this?

PS: Is Record<T> (semantically) the same as {[ key: string ]: T | undefined }?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

UPDATE FOR TYPESCRIPT 4.1+

There is now a --noUncheckedIndexedAccess compiler option which, when enabled, includes undefined when reading from index signature properties. This option is not part of the --strict suite of compiler options, because it's too much of a breaking change and some of the workarounds are annoying.


PRE-TS4.1 ANSWER:

This has been raised as a suggestion (see microsoft/TypeScript#13778) and has essentially been declined (although it is listed as "awaiting more feedback") because it is expected to cause more bugs than it would fix. You're right that the current situation is inconsistent and technically incorrect/unsound, but it is not one of TypeScript's goals to "apply a sound or 'provably correct' type system. Instead, [it should] strike a balance between correctness and productivity."

TypeScript doesn't actually enforce every possible key matching the index to be present (so index signature properties are effectively optional), but it does enforce that any such key which is present has a defined value of the right type... this is one of the few places in TypeScript where missing and undefined are distinguished.

As you noted, if you want your own index-signature types to behave the same as other optional properties (meaning that undefined is automatically a possible value), you can add | undefined to the property type. If you want existing index-signature types to behave this way (like Array), you'll have to fork your own copy of the standard library and do it for yourself. They won't do it upstream because it would make lots of people very sad to deal with this.

If you really want to see this changed, you might want to visit the GitHub issue and comment or upvote, but I wouldn't hold my breath... your time is probably better spent moving past this (I speak from experience... I've had to do this several times when dealing with TypeScript's pragmatic inconsistencies.)

I hope that helps. Good luck!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...