microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.21k stars 12.51k forks source link

Argument of type [type] is not assignable to parameter of type [typeof itself] #60508

Closed lionel-rowe closed 1 week ago

lionel-rowe commented 1 week ago

🔎 Search Terms

Type narrowing, typeof, type casting, as, argument of type is not assignable to parameter of type typeof itself

🕗 Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAGlC8UDeUDWBLAdgEwFxQHIBDAqAH0ICNSBfAKDuwgGMAbIgJ2gDMBXTZsHQB7TFG6YAFJXwoMOfAWpQaASnwA3YemwMmbTtGaiAzsCgAPfDAbpuUSRYB087AniIlBVcjpR-4lIWqn4BEo5QRCZQoJDC9sGh-uEWkdGxEPGWUABkyGhYeDHgmQkuhSoh9EA

💻 Code

type X = { kind: 'a' | 'b' }

declare function fn(b: { kind: 'b' }): void

declare const x: X

if (x.kind === 'b') {
    // Argument of type 'X' is not assignable to parameter of type '{ kind: "b"; }'.
    fn(x)
    // Argument of type 'X' is not assignable to parameter of type '{ kind: "b"; }'.
    fn(x as typeof x)
    // ok
    fn(x as typeof x & { kind: typeof x.kind })
}

🙁 Actual behavior

First 2 versions give type errors.

🙂 Expected behavior

All 3 versions pass type checking.

Additional information about the issue

It seems like all the type info is available and inferred correctly by TS, given that the third version works, which makes it even weirder that the first two fail. How are x and x as typeof x different from x as typeof x & { kind: typeof x.kind }?

jcalz commented 1 week ago

Duplicate of #42384

lionel-rowe commented 1 week ago

Duplicate of #42384

@jcalz Thanks! I was sure someone would have raised it before but searching threw up nothing relevant. Closing as dupe.