1
const record = {
    foo: () => ({ foo: 1 }),
    bar: () => ({ bar: 1 }),
}

function getRecord<T extends keyof typeof record>(type: T) {
    return record[type];
}

const obj = getRecord(`foo`);
// if line 7 is:        return record[type];
// typeof obj will be:  () => { foo: number; }

// but if line 7 is:    return record[type]();
// typeof obj will be:  { foo: number; } | { bar: number; }
obj

Playground link

When the return value is not called, TypeScript can successfully infer the return type to be () => { foo: number }, but when the return value is called, the type inference broadened to { foo: number; } | { bar: number; }. Why is this happening?

4
  • I would suggest making it clearer that you're looking for the reason why it's not inferring the correct type. Commented Nov 20, 2020 at 8:10
  • Definitely. I've updated the description. Commented Nov 20, 2020 at 8:13
  • if I understand your request, you might want to add the return type explicitly (ReturnType<typeof record[T]>), like this Commented Nov 20, 2020 at 8:22
  • Type casting can do the trick, but we want to avoid it as much as possible. Are there any issues about this behavior currently? TypeScript issue tracker is a huge mess and I even can't come up with anything to search with.. Commented Nov 20, 2020 at 8:42

1 Answer 1

2

The return type of:

function getRecord<T extends keyof typeof record>(type: T) {
    return record[type];
}

Is (typeof record)[T]. As you can see, the generic type parameter influences the return type of the function when function is called.


In the second example:

function getRecord<T extends keyof typeof record>(type: T) {
    return record[type]();
}

The return type is { foo: number } | { bar: number }. Here the generic parameter doesn't affect it (already used to pre-evaluate the return type).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.