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

Const indexed access issue β€” should attempt widening to a mapped type #51156

Closed
smichelJW opened this issue Oct 12, 2022 · 3 comments
Closed
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@smichelJW
Copy link

smichelJW commented Oct 12, 2022

Bug Report

@ahejlsberg This issue seems nearly identical to #47368, but this time for const object types which are assignable to the mapped type.

πŸ”Ž Search Terms

const indexed access; object literal indexed access; object literal widen; widen mapped type

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about indexed access.

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type ArgMap = { a: number, b: string };
type Func<K extends keyof ArgMap> = (x: ArgMap[K]) => void;
type Funcs = { [K in keyof ArgMap]: Func<K> };

const funcs = {
    a: (x: number) => {},
    b: (x: string) => {},
};

function f1<K extends keyof ArgMap>(key: K, arg: ArgMap[K]) {
    funcs[key](arg);
}

function f2<K extends keyof ArgMap>(key: K, arg: ArgMap[K]) {
    const func = funcs[key];  // Type Funcs[K]
    func(arg);
}

function f3<K extends keyof ArgMap>(key: K, arg: ArgMap[K]) {
    const func: Func<K> = funcs[key];  // Error, Funcs[K] not assignable to Func<K>
    func(arg);
}

πŸ™ Actual behavior

Unexpected error in example above.

It's unexpected because throwing away type information makes this type check correctly, by widening with either const funcs: Funcs (all examples) or const func: Funcs[K] (in f2). So the compiler actually is able to confirm that indexed type is assignable to the mapped type, it just doesn't try without being explicitly prompted.

πŸ™‚ Expected behavior

No errors in example above.

@MartinJohns
Copy link
Contributor

MartinJohns commented Oct 12, 2022

This is working as intended.

K can also be a union type, like "a" | "b". In this case your type Funcs[K] resolves to (x: number) => void | (x: string) => void. When trying to call a union like this, you must provide a value that's compatible with all possible argument types, because the compiler doesn't know whether it has a function accepting a string or a number - so the type you must provide must be both: string & number. But such a type can't be represented, so you end up with never.

f1<"a" | "b">("a", "abc")
f1<"a" | "b">("b", 123)

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Oct 12, 2022
@RyanCavanaugh
Copy link
Member

The error is correct, though if you formulate your arguments to a specific pattern, a convenient soundness hole will be created for you. See #47109

@typescript-bot
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants