-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mapped array/tuple types can't be used as generic with a constraint #48740
Comments
I think it is explained in #48398.
|
The fact tuple keys aren't subtypes of
No, that doesn't work, it causes the final type in the example to become: const locals: [Local<I32 | Externref>, Local<I32 | Externref>] Which is not correct, the existing |
You are right. Since what we need is only 'numeric like' types in type _GetKeysFromLength<
L extends number,
R extends readonly unknown[] = [],
> = number extends L ? number : R['length'] extends L ? R[number] : _GetKeysFromLength<L, readonly [R['length'], ...R]>;
type KeyOf<T extends unknown[]> = _GetKeysFromLength<T['length']> extends infer U extends number ? U : never;
// for versions prior to v4.7
// type KeyOf<T extends unknown[]> = _GetKeysFromLength<T['length']> extends infer U ? U extends number ? U : never : never;
type R1 = KeyOf<[1,2,3]>;
// ^? type R1 = 0 | 2 | 1
type R2 = KeyOf<number[]>;
// ^? type R2 = number
type LocalsFor<Type extends Array<ValType>> = {
[K in KeyOf<Type>]: Local<Type[K]>
};
const locals: LocalsFor<[I32, Externref]> = [
new Local(new I32()),
new Local(new Externref()),
]; // seems OK now!
var l0 = locals[0]
// ^? var l0: Local<I32>
var l1 = locals[1]
// ^? var l1: Local<Externref> |
This is a correct error.
This is the incorrect assumption. Matching the constraint type M = ReadonlyArray<ValType> & { k: boolean };
type LocalsFor<Type extends ReadonlyArray<ValType>> = {
// Type 'Type[K]' does not satisfy the constraint 'ValType'.
// Type 'Type[keyof Type]' is not assignable to type 'ValType'.
// Type 'Type[string] | Type[number] | Type[symbol]' is not assignable to type 'ValType'.
// Type 'Type[string]' is not assignable to type 'ValType'.(2344)
[K in keyof Type]: Local<Type[K]>
};
type G = LocalsFor<M>;
type X = G["k"]; // x: Local<boolean>, a constraint violation |
These bizarre rules make the whole point of "homomorphic mapped types" seem fairly weak and unreliable, like if there's gonna be special casing for arrays in mapped types to not map stuff like methods, why would we want it to map other random properties that might be attached onto the array? (as an example, symbol-keyed protocols like The amount of bizarre behaviours in the mapped types feature just constantly surprises me, I don't see how any developers who aren't intimately familiar with TypeScript's internals are expected to have any reasoning about these complicated features (and it doesn't help that that handbook doesn't even mention arrays are (kind've) homomorphic in mapped types to begin with, this was something just mentioned once when the feature was released in the associated release blog post). |
Either way, I think I'll reopen the other issue because that one at the very least checks the keys for "numeric"-ness. |
Every single rule we've added to mapped types was put there to remove some other surprise π€·ββοΈ |
So is #27995 not really a bug then? |
This has changed from "working as intended" to "fixed" by #48837. Not sure if anyone wants to alter tags here. |
Bug Report
π Search Terms
mapped tuple type
π Version & Regression Information
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
It produces an error in the mapped type that
Type[K]
doesn't satisfy the constraint.π Expected behavior
There should be no error, as mapped types do not map over all keys in the array/tuple, it should only consider
Type[K]
to be the numeric keys of the tuple, i.e.Type[K]
in the mapped type will only ever be (subtypes of)ValType
because ultimatelyK
will only be assigned to the numeric keys ofType
as it's an array type.In this particular case, we have an explicit
Type extends ReadonlyArray<ValType>
so TypeScript should be able to deduce just fine that this particular mapped type will only ever be over an array, and hence should be able to deduce thatType[K]
will only ever beType[number]
(orType[`${ number }`]
for tuples).I had another issue, however I closed it and opened this one because this is likely the fundamental cause of both problems.
The text was updated successfully, but these errors were encountered: