Uh oh!
There was an error while loading. Please reload this page.
Const contexts for literal expressions - #29510
Conversation
Jack Williams (jack-williams)
commented
Jan 21, 2019
Did you consider using |
A question: letobj={x: 10,z: {a: {b: 42}}asconst};to initialize a type like: letobj: {x: number;z: {readonlya: {readonlyb: 42;};};};If yes, probably you want to add a test like that. |
Tom Crockett (pelotom)
commented
Jan 21, 2019
This is AWESOME. Thank you Anders Hejlsberg (@ahejlsberg)! |
Anders Hejlsberg (ahejlsberg)
commented
Jan 22, 2019
I did not. Can you provide an example of what you mean exactly?
Yes.
Sure. |
Jack Williams (jack-williams)
commented
Jan 22, 2019
Anders Hejlsberg (@ahejlsberg) Currently neither of these give excess property errors: constu: {x: number}|{y: string}={x: 42,y: "helloworld"};consti: {a: {x: number}&{y: string}}&{b: boolean}={a: {x: 42,y: "y",z: "excess"},b: true};Though these EPC bugs are on the backlog to fix for all literals, there are 2 obstacles:
I'm suggesting that maybe these give errors by using const contexts as a marker to enable complete and correct EPC: constu: {x: number}|{y: string}={x: 42,y: "helloworld"}asconst;// error 'y' is excess (or some better error)consti: {a: {x: number}&{y: string}}&{b: boolean}={a: {x: 42,y: "y",z: "excess"},b: true}asconst;// error 'z' is excessBasically using const contexts as a way to trial full-EPC in a way that does not introduce any breaking changes. If the trial is successful then full-EPC can be rolled out to all literals with const being ahead of the curve; if the trail does not work out then full-EPC can be removed in const contexts in a non-breaking way. |
Can it be also assumed in certain situations? Like: consta: 12;// type is 12letx={// Can this be `const`? // Either always, or only when it's `readonly x1: a`. It's fine either way.x1: a};The situation here being assignment to a constant, and fine to require Also, one important situation (as mentioned with more details): functioncreateAction<TType>(type: TType){// Not concerned with return types here, but inferred argument typereturn{type: type};}// Today this gets inferred as string, but can string literal be inferred as itself?constdoStuff=createAction("DO_STUFF");The situation here being sending a literal (string or number) to a function with argument type being generic and inferred from usage. It'll be nice to avoid |
Mihail Malo (qm3ster)
commented
Jan 23, 2019
Next step: allowing |
Tal Atlas (tal)
commented
Jan 24, 2019
Is the |
Tom Crockett (pelotom)
commented
Jan 24, 2019
That would require adding a new keyword for dubious benefit. Personally I think |
Tom Crockett (pelotom)
commented
Jan 24, 2019
But it was already a literal, before you added |
be it a |
Tomasz Ducin (ducin)
commented
Jan 24, 2019
Question: if the |
ZpdDG4gta (zpdDG4gta8XKpMCd)
commented
Jan 24, 2019
to those who believes in |
Anders Hejlsberg (@ahejlsberg) Would there be any way to dynamically concatenate two literal types to produce a new literal type using this For example, in a function like... constconcatLiterals=<Aextendsstring,Bextendsstring>(a: A,b: B)=>`${a}{b}`asconst// or (a + b) as constI'm assuming the dynamic nature of the above here would prevent this from working, and it would still widen the type to It would be great to have some sort of type-level concat helper for literals like this.... so that you could do something like: (a+b)as(const: A+B)or `${a}{b}`as(const: ConcatLit<A,B>)or something along those lines. |
Apparently |
I agree with I suspect that we'll end up with a quick fix like |
ZpdDG4gta (zpdDG4gta8XKpMCd)
commented
Jan 25, 2019
oh let's not forget what readonly really is #13002 |
Somehow I knew exactly what you linked to before I clicked on it. |
Bnaya Peretz (Bnaya)
commented
Jan 25, 2019
This is probably out of the scope, but: |
Nick Ribal (elektronik2k5)
commented
Jan 25, 2019
+1 for |
Mukundan Kidambi (masterkidan)
commented
Jan 25, 2019
A question regarding this.... interfacefoo{bar: string}functionfoobar(): ReadonlyArray<foo>{}Is it possible to return something like so functionfoobar(): fooasconst{}Would really like to have a use case like the above included as well, as it would help a lot with immutability. |
Is there a way to allow constant string to represent string literals? For example: In the case above, "mod" is of type "any" because the compiler doesn't recognize the string literal in the constant I may also add, it seems very difficult to import namespaces using dynamic imports, which I think is another terrible oversight. That doesn't even make sense. A namespace, while a type, is still a reference under the hood, and thus should still be importable dynamically somehow; perhaps like: I think all this would aim to better support dynamic imports "on demand" instead of modules forcibly loading every single module when some may not be needed at all, It could also help promote faster initial page loads in many cases. ;) |
Meligy (Meligy)
commented
Jul 15, 2019
James (@rjamesnw) since this PR is already merged I don't expect that you can get traction for anything new, but this is a good one actually. Can you please open a new issue for it? Thanks. |
You’re right, sorry, it also occurred to me and I was going to get to doing so asap. ;) Update: Issue created: #32401 |
When we want to use other TypeScript version and we do: `npm install typescript@3.5.3 -D` But when we use new features like const casting microsoft/TypeScript#29510 it does not compile. Instead of that if we use: `yarn add typescript@3.5.2` Everything works
This commit refactors the SignatureType enum into an array of strings declared [as const](microsoft/TypeScript#29510). This allows the SignatureType type to be expressed as a union type, which works a bit better when parsing a users provided string. This is some simple refactoring in preparation for declarative function signatures.
This commit refactors the SignatureType enum into an array of strings declared [as const](microsoft/TypeScript#29510). This allows the SignatureType type to be expressed as a union type, which works a bit better when parsing a users provided string. This is some simple refactoring in preparation for declarative function signatures. BREAKING CHANGE: exported SignatureType type is converted from an enum to a union type
This commit refactors the SignatureType enum into an array of strings declared [as const](microsoft/TypeScript#29510). This allows the SignatureType type to be expressed as a union type, which works a bit better when parsing a users provided string. This is some simple refactoring in preparation for declarative function signatures. BREAKING CHANGE: exported SignatureType type is converted from an enum to a union type
Why would someone use letnumbers=[1,2,3]asconst; |
BeautyInNorth
commented
Jun 23, 2022
Excuse me,why is the error reported? |
Tom Crockett (pelotom)
commented
Jun 23, 2022
Because not every element of the array has an |
I found out that letx=12;x=2asconst;x=5;console.log(x);// 5Also you'll get no error if the reassigned value is like the previous value: letx=[1,2]asconst;x=[1,2];// works |
Brandon Pittman (brandonpittman)
commented
Nov 9, 2022
Is there a way to type an array of objects declared using |

With this PR we introduce
constassertions which favor immutability in the types inferred for literal expressions (inspired by suggestions in #10195, #20195, and #26979). Aconstassertion is simply a type assertion that uses the reserved wordconstas the type name:A
constassertion establishes a const context in whichConst contexts do not otherwise affect types of expressions, and expressions in const contexts never have a contextual type.
An expression
xis said to occur in a const context ifxisconstassertion, orNote in particular that const contexts extend into nested array and object literals. For example, the declaration
corresponds to
A
constassertion requires the operand to be a string, number, bigint, boolean, array, or object literal, optionally enclosed in one or more levels of parentheses. It is an error to apply aconstassertion to expressions of other forms.Fixes#10195.
Fixes#20195.
Fixes#26979.