| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
|
Did you consider using const as a hook for enabling deep excess property checking for arbitrary union and intersection types? |
Sorry, something went wrong.
|
A question: let obj = {
x: 10,
z: { a: { b: 42 } } as const
};to initialize a type like: let obj: {
x: number;
z: {
readonly a: {
readonly b: 42;
};
};
};If yes, probably you want to add a test like that. |
Sorry, something went wrong.
|
This is AWESOME. Thank you Anders Hejlsberg (@ahejlsberg)! |
Sorry, something went wrong.
I did not. Can you provide an example of what you mean exactly?
Yes.
Sure. |
Sorry, something went wrong.
|
Anders Hejlsberg (@ahejlsberg) Currently neither of these give excess property errors: const u: { x: number } | { y: string } = { x: 42, y: "helloworld" };
const i: { 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: const u: { x: number } | { y: string } = { x: 42, y: "helloworld" } as const; // error 'y' is excess (or some better error)
const i: { a: { x: number } & { y: string } } & { b: boolean } = { a: { x: 42, y: "y", z: "excess" }, b: true } as const; // 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. |
Sorry, something went wrong.
|
Can it be also assumed in certain situations? Like: const a: 12; // type is 12
let x = {
// 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 readonly for this. Also, one important situation (as mentioned with more details): function createAction<TType>(type: TType) {
// Not concerned with return types here, but inferred argument type
return {
type: type
};
}
// Today this gets inferred as string, but can string literal be inferred as itself?
const doStuff = 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 const in createAction("DO_STUFF" const). |
Sorry, something went wrong.
|
Next step: allowing importing JSON modules as const |
Sorry, something went wrong.
|
Is the const keyword from somewhere else? To me it's confusing and easy to conflate with the const variable declaration keyword. immutable would be clearer for me. |
Sorry, something went wrong.
That would require adding a new keyword for dubious benefit. Personally I think readonly would have been preferable to const (since it has the effect of adding readonly modifiers deeply through a tree of types). But const has the advantage of being short 🤷♂️ |
Sorry, something went wrong.
But it was already a literal, before you added as literal... |
Sorry, something went wrong.
|
be it a wanker i would not say a thing, but sure let's nitpick and bike shed this thing to the bone, because we can and it's just useless otherwise |
Sorry, something went wrong.
|
Question: if the as const clause recursively adds readonly to object literals, why not calling it as readonly? Not a big issue, but introduces some ambiguity with the native ES6 const which has slightly different meaning than TS' readonly |
Sorry, something went wrong.
|
to those who believes in readonly modifiers, will it make your array properties readonly "deeply through a tree of types"? |
Sorry, something went wrong.
|
Anders Hejlsberg (@ahejlsberg) Would there be any way to dynamically concatenate two literal types to produce a new literal type using this const context? For example, in a function like... const concatLiterals = <A extends string, B extends string>(a: A, b: B) =>
`${a}{b}` as const // 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 string, but this capability is something I've wanted for a while. 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. |
Sorry, something went wrong.
|
Apparently as readonly instead of as const was considered and decided against, see the meeting notes. I understand the reasoning, but I still think as readonly is more intuitive 😛 |
Sorry, something went wrong.
|
I agree with as const being kind of confusing. Maybe the only reason I don't feel as strongly against it is the explanation itself is relatively consistent with the current distinction of const and readonly. I suspect that we'll end up with a quick fix like Did you mean 'as const'? when someone writes as readonly. |
Sorry, something went wrong.
|
oh let's not forget what readonly really is #13002 |
Sorry, something went wrong.
|
Somehow I knew exactly what you linked to before I clicked on it. |
Sorry, something went wrong.
|
This is probably out of the scope, but: |
Sorry, something went wrong.
|
+1 for as readonly because that's what it actually does. |
Sorry, something went wrong.
|
A question regarding this.... interface foo {
bar: string
}
function foobar(): ReadonlyArray<foo> {
}Is it possible to return something like so function foobar(): foo as const {
}Would really like to have a use case like the above included as well, as it would help a lot with immutability. |
Sorry, something went wrong.
|
Is there a way to allow constant string to represent string literals? For example: const moduleName = "../../../Project/src/Mod";
async function doSomething() {
var mod = await import(moduleName); // (works only if a string literal at the moment)
}
In the case above, "mod" is of type "any" because the compiler doesn't recognize the string literal in the constant moduleName (for literal strings, the types are correctly pulled). I'm not sure if this was an oversight, but it makes sense to allow it, since constant strings cannot be reassigned. The only workaround is to wrap await import("../../../Project/src/Mod"); in a function: async function getMod() { return import("../../../Project/src/Mod"); }
async function doSomething() {
var mod = await getMod(); // (method required since const strings cannot be used to import module type)
}
I may also add, it seems very difficult to import namespaces using dynamic imports, which I think is another terrible oversight. async function doSomething() {
var mod = await import("../../../Project/src/Mod"); // (forced to use a string literal to get typings)
var o: mod.SomeClass; // ERROR, cannot find namespace 'mod'
// var o: InstanceType<typeof mod.SomeClass>; // workaround1
// var o: import("../../../Project/src/Mod").SomeClass; // workaround2 (who wants to keep typing full paths? A const string would be nice here.)
}
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: async function doSomething() {
import mod = await import("../../../Project/src/Mod"); // (forced to use a string literal to get typings)
var o: mod.SomeClass;
}
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. ;) |
Sorry, something went wrong.
|
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. |
Sorry, something went wrong.
|
You’re right, sorry, it also occurred to me and I was going to get to doing so asap. ;) Update: Issue created: #32401 |
Sorry, something went wrong.
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 let for declaring a variable which is typed with as const? let numbers = [1, 2, 3] as const; |
Sorry, something went wrong.
|
Excuse me,why is the error reported? const arr = [
{ age: 12, fruits: 'apple' },
{ age: 16, fruits: 'cherry' },
{ fruits: 'banana' },
] as const
type Fruits = typeof arr[number]['fruits']
arr.map(({ age, fruits }) => {
//Property 'age' does not exist on type
//'{ readonly age: 12; readonly fruits: "apple"; } | { readonly age: 16; readonly fruits: "cherry"; } | { readonly fruits: "banana"; }'.
console.log(age)
})
|
Sorry, something went wrong.
Because not every element of the array has an age property. |
Sorry, something went wrong.
|
I found out that as const does not work after a variable has been declared: let x = 12;
x = 2 as const;
x = 5;
console.log(x); // 5Also you'll get no error if the reassigned value is like the previous value: let x = [1, 2] as const;
x = [1, 2]; // works |
Sorry, something went wrong.
Is there a way to type an array of objects declared using as const if some of the objects lack properties that other objects have? |
Sorry, something went wrong.
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
With this PR we introduce const assertions which favor immutability in the types inferred for literal expressions (inspired by suggestions in #10195, #20195, and #26979). A const assertion is simply a type assertion that uses the reserved word const as the type name:
A const assertion establishes a const context in which
Const contexts do not otherwise affect types of expressions, and expressions in const contexts never have a contextual type.
An expression x is said to occur in a const context if x is
Note in particular that const contexts extend into nested array and object literals. For example, the declaration
corresponds to
A const assertion 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 a const assertion to expressions of other forms.
Fixes #10195.
Fixes #20195.
Fixes #26979.