Repository navigation
as const does not always narrow array literals to tuple typesΒ #57727
Description
π Search Terms
as const, narrow, widen, tuple
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
as constnarrowing.
β― Playground Link
π» Code
interface TS {
new (...args: any[]): any;
}
interface AS<P extends PS> {
[a: string]: ReadonlyArray<keyof P>;
}
interface PS {
[p: string]: TS;
}
type Args<T extends ReadonlyArray<keyof P>, P extends PS> = T extends [infer First, ...infer Rest]
? [First extends keyof P ? InstanceType<P[First]> : never, ...Args<Rest extends ReadonlyArray<keyof P> ? Rest : [], P>]
: [];
interface R<A extends AS<P>, P extends PS> {
f<D extends keyof A>(d: D, a: Args<A[D], P>): void;
}
const x = {
b: ['q'] as ['q'], // error without as ['q']
c: ['q'],
} as const;
const y = { q: Number } as const;
function test(r: R<typeof x, typeof y>) {
r.f('b', [5]);
}π Actual behavior
Without the as ['q'] cast (see comment in code), the code fails to compile, presumably due to not correctly inferring the narrow tuple type and inferring an array type instead.
π Expected behavior
When using the as const assertion on an object literal, TypeScript is expected to infer the most specific literal types for all properties, including narrowing array literals to tuple types. However, in the context of a mapped type and conditional type, this behavior seems to be inconsistent, leading to a type mismatch error.
Additional information about the issue
The issue occurs in the context of mapped types (AS<P>) and conditional types (Args<T, P>). The as const assertion is expected to provide the most specific literal types, but it fails to narrow the array literal to a tuple type automatically, leading to the type mismatch error.
Possible Solution:
Ensure that the as const assertion consistently narrows array literals to tuple types within object literals, even in the context of mapped types and conditional types, aligning with the expected behavior described in the TypeScript documentation.
Activity
Andarist commentedon Mar 11, 2024
I didn't analyze what you are trying to achieve here but I was able to fix ur problem by adding
readonlyto your inference target inArgs: TS playgroundRyanCavanaugh commentedon Mar 11, 2024
I don't see a defect demonstrated here. The additional
aschanges the type of the expression and as a result, type computations change.It's the same as the difference between these two declarations:
vs
jflatow commentedon Mar 12, 2024
Thanks, that indeed fixes the error.
jflatow commentedon Mar 12, 2024
Perhaps, but the change in type computations is at least odd to me. By adding the
as ['q']it does indeed seem to change from interpreting as a tuple to an array in the given context. But the additionalreadonlyseems to prevent that. I'm confused why this is happening without it but glad it makes sense to you.typescript-bot commentedon Mar 15, 2024
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes.