question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Type guards not working for indexed types with generics

See original GitHub issue

TypeScript Version: 2.7

Search Terms: indexed type guard

Code

function f<T extends string>(q: {[k:string]: number | string}, t: T) {
    const v= q[t];
    if (typeof(v)!=="string") {
        const vv: number = v;
    }
}

Expected behavior: Type of v is string|number, and in the if it is just number. Compiles.

Actual behavior: Assignment to vv doesn’t compile: string not assignable to number. When hovering, type of v is { [k: string]: string | number; }[T], so eliminating string from it does not change the type, it is still the same, and only when assigning to vv it gets resolved to string|number which then causes compilation error.

Changing type of t to string fixes the problem. The problem also appears if q has type keyed by [k in T].

Playground Link: link

Related Issues:

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:1
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
mhegazycommented, Mar 2, 2018

Narrowing with primitives really does not work with generics… here is a simpler example:

function f<T extends string | number>(t: T) {
    if (typeof t !== "string") {
        const v: number = t; // Error
    }
}

The issue here is that T has to stay generic. any narrowing we do has to be on the type of the constraint, so in if block t should be T extends number instead of T extends number | string.

1reaction
TPRealcommented, Mar 2, 2018

The problem is that this is a regression - my original example, or something equivalent to it, used to work in some earlier version (I’m not sure which exactly) because q[t] was immediately treated as string | number, at least in the case when the key was declared as [k in T]. So I’m quite sure this is a bug, not just a suggestion.

I think that this is why @mhegazy’s example is different than mine, where the type does not really depend on T.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why does Typescript not infer the type for a generic type guard ...
I found a solution ! I can use the same technique like sequelize uses it in its typings for the model attribute types....
Read more >
Generic type guard in Typescript - DEV Community ‍ ‍
But we get this error: Type 'T' cannot be used to index type 'typeMap'. In the case where T is not a constructor...
Read more >
Documentation - Advanced Types - TypeScript
A type guard is some expression that performs a runtime check that guarantees the type in some scope. Using type predicates. To define...
Read more >
How To Do Anything in TypeScript With Type Guards
Type guards are conditional checks that allow types to be narrowed from ... we check exists in multiple cases, the narrowing will not...
Read more >
Generics - TypeScript
While using any is certainly generic in that it will cause the function to accept any and all types for the type of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found