Skip to content
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

TS2345 error with derivated types from a map of types #35613

Closed
lgraziani2712 opened this issue Dec 10, 2019 · 5 comments
Closed

TS2345 error with derivated types from a map of types #35613

lgraziani2712 opened this issue Dec 10, 2019 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@lgraziani2712
Copy link

TypeScript Version: 3.7.2

Search Terms: ts2345 derivated type error

I really don't know how to describe this bug in short terms.

Code

enum A {
    a = 'a',
    b = 'b'
}

interface ObjA {
    prop1: string;
}
interface ObjB {
    prop2: number;
}

type PayloadMap = {
    [A.a]: ObjA;
    [A.b]: ObjB;
}

type Content<T extends A> = {
    type: T;
    payload: PayloadMap[T];
}

function processContent<T extends A>(content: Content<T>) {
    parserPayload[content.type](content.payload);
//                              ^=========== here is the error
}

const parserPayload: { [key in A]: (payload: PayloadMap[key]) => any } = {
//                                           ^============ because this is treated
//                                                         as an intersection
    a: payload => payload.prop1,
    b: payload => payload.prop2,
}

Expected behavior: To correctly know that PayloadMap[key] is in fact the same as PayloadMap[T] since key matches T.

Actual behavior:

Argument of type 'PayloadMap[T]' is not assignable to parameter of type 'ObjA & ObjB'.

Playground Link: https://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=30&pc=2#code/KYOwrgtgBAglDeAoKKoEMoF4oHI04BplUAjLXEnRAX0UQEsQAXYAJwDM0BjYKAeRIArOElRQADqwD24gIwAuKAGcmrRgHMA3DQbM2nHvyEAhBMRSSZAJkXgIJNttqImAT3G8ACmlcAbKWgAJgCyaOLkoqgA2jAAdGgAuooCwtpiMbEkSUaCxk50bh5QAMJSeswAPAAqUMAAHiwggUqwAHwR5lCFwIpVaajiPv5Bit5+ASFhUVUJ+YjsYCBcTPRlEtI8Skql5UzVtQ2gzW0AFFxljUyKO5fVrQCUZmKDrEpsY8OBUee7sd0JZwuoCYsUG4yC9zmPxUEjQr3eQwmingUCiAGtgK4oIxYNkTmDPqNEUFQuJ0ZiEo9MO00CAsdQOmI0IoCRMsO1WUFQdI5EQxCQWcTAuzYeDAtzrERqEA

Related Issues:

@fatcerberus
Copy link

Indexed access produces intersection type => most likely caused by #30769.

@RyanCavanaugh
Copy link
Member

TS doesn't know that this is OK to do. You could have written this, which would be seen equivalently:

function processContent<T extends A>(content1: Content<T>, content2: Content<T>) {
    parserPayload[content1.type](content2.payload);
}
declare const a: Content<A.a>, b: Content<A.b>;
// Causes a runtime error, but is an OK call
processContent(a, b);

@RyanCavanaugh
Copy link
Member

Duplicate #31445

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Dec 10, 2019
@lgraziani2712
Copy link
Author

TS doesn't know that this is OK to do. You could have written this, which would be seen equivalently:

BTW, isn't that a kind of bug that TS doesn't check? There are a lot of business logic bugs with correct typings that TS isn't able to catch and that's OK. Isn't the bug you're exemplifying one of that kind?

Thank you for your rapid response!

@RyanCavanaugh
Copy link
Member

That's a type error, not a business logic error. You can construct examples that observe a string where a number is expected, for example.

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

3 participants