Skip to content

Mapped generic type loses types during inference #56861

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

Closed
Jamesernator opened this issue Dec 24, 2023 · 3 comments
Closed

Mapped generic type loses types during inference #56861

Jamesernator opened this issue Dec 24, 2023 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@Jamesernator
Copy link

πŸ”Ž Search Terms

mapped tuple type, const inference

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about mapped types

⏯ Playground Link

https://www.typescriptlang.org/play?ssl=13&ssc=1&pln=1&pc=1#code/MYGwhgzhAEAiCmwD2ATeAnAPAFQHzQG9oBfAKFNEhmwFcAHEeBZNLZAOwgBdpaH5sATzrxo8AB5d47FDABK8MCiTsQggILp0YQZnY0AtgCMMufBKkyYzVBhz1GQkfgKlo76B27oawLknQACmkudEEbVggALkJoAG0AaWgAS3ZoAGt4QSQAM14HAWF4AF0YiLs+RyLE4vxiAEpCNw8WiHoMQPqAbmb3MjJSNEp0US8eIdt0AEYyxEm9QxN0XB6h8BHPFW5oCdYAJlmWO29UgHMV0gB6S+gASXYcjBGUaH98-nKsfWMMONqKLY8LgFT7QAC80HY8AA7u9GJ9AnFdhgpgAaHZzfbFbqkIA

πŸ’» Code

class Decoder<T> { }

class TupleDecoder<const TupleType extends ReadonlyArray<number>> extends Decoder<TupleType> {
    constructor(entryDecoders: { [K in keyof TupleType]: Decoder<TupleType[K]> }) {
        super();
    }
}

declare const decoder1: Decoder<number>;
declare const decoder2: Decoder<string>;
// Inferred to TupleDecoder<number[]>
const tupleDecoder = new TupleDecoder([decoder1, decoder2]);

πŸ™ Actual behavior

The type of tupleDecoder is inferred to TupleDecoder<number[]>

πŸ™‚ Expected behavior

It should be inferred to be TupleDecoder<readonly [number, string]>.

Additional information about the issue

I believe this problem is probably two seperate problems.

One is that const ... extends ReadonlyArray<any> isn't being considered for mapped types.

Second is that inference is not picking up the string type in the array due to the mapped type.

@jcalz
Copy link
Contributor

jcalz commented Dec 24, 2023

Decoder<T> has no structural dependence on T so there's nothing useful to infer from, see the FAQ on unused type parameters. If you fix this then you see that decoder2, a Decoder<string>, does not satisfy the Decoder<number> constraint. If you fix that by making the constraint any instead of number, then you get TupleDecoder<(string | number)[]>.

That gets you to "const T extends β‹―" not working well for mapped types, which looks like #53813, which currently I'd work around by using variadic tuple types, giving this:

class Decoder<T> {
    declare prop: T; // you need a structural dependency 
}

class TupleDecoder<const TupleType extends ReadonlyArray<any>> extends Decoder<TupleType> {
    //                                not number ----->  ^^^
    constructor(entryDecoders: [...{ [K in keyof TupleType]: Decoder<TupleType[K]> }]) {
        //                     ^^^^ <-- variadic tuple to hint you want a tuple --->^
        super();
    }
}

declare const decoder1: Decoder<number>;
declare const decoder2: Decoder<string>;
const tupleDecoder = new TupleDecoder([decoder1, decoder2]);
// const tupleDecoder: TupleDecoder<[number, string]>

Playground

To recap, the only problem I see here is the one that looks like a duplicate of #53813. Everything else behaves as expected.

@Andarist
Copy link
Contributor

And with #56555 you won't even have to "hint" that you want a tuple here - since the usage of a mapped type will already be treated as such a hint: TS playground

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jan 2, 2024
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jan 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants