(t: TT, p: M[TT]) { switch" /> (t: TT, p: M[TT]) { switch" /> (t: TT, p: M[TT]) { switch"/>

Narrow generic mapped argument

16 Views Asked by At

Here is code:

type T = 'a' | "b"
type M = {
  a: 1,
  b: 2
}

function a(a: 'a') {}
function m1(a: 1) {}

function f<TT extends T>(t: TT, p: M[TT]) {
  switch (t) {
    case "a": {
      a(t)
      m1(p) // Argument of type '1 | 2' is not assignable to parameter of type '1'
      break
    }
  }
}

Why p wasn't narrowed to 1? Are there a neat workaround without type casts?

1

There are 1 best solutions below

0
Behemoth On BEST ANSWER

TypeScript is unable to recognize that p corrolates with t as explained in microsoft/TypeScript#35873. You'll need another type guard to narrow p. The most straightforward syntax is to use switch (true) narrowing which was recently added in TypeScript 5.3.

type T = "a" | "b";
type M = {
  a: 1;
  b: 2;
};

declare function a(a: "a"): void;
declare function m1(a: 1): void

function f<TT extends T>(t: TT, p: M[TT]) {
  switch (true) {
    case t === "a" && p === 1:
      a(t);
      m1(p);
      break;
  }
}

TypeScript Playground