Skip to content

Generic function type gets inferred to any without explicit typingΒ #51831

@KSchala

Description

@KSchala

Bug Report

Type has to be explicit defined while being resolved correctly?!

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried

πŸ”Ž Search Terms

Type inference, Union, Pattern

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type Union<T extends object> = {
  [P in keyof T]: ({ [Q in "kind"]: P } & T[P]) extends infer U ? { [Q in keyof U]: U[Q] } : never
}[keyof T]
type UnionMap<U extends { kind: string }> = { [K in U["kind"]]: U extends { kind: K } ? U : never }
type ExhaustivePattern<T extends { kind: string }, R> = { [K in T["kind"]]: (union: UnionMap<T>[K]) => R };
type NonExhaustivePattern<T extends { kind: string }, R> = { [K in T["kind"]]?: (union: UnionMap<T>[K]) => R } & {_: (union: T) => R};
type Pattern<T extends { kind: string }, R> = ExhaustivePattern<T, R> | NonExhaustivePattern<T, R>;


function match<U extends { kind: string }, T>(union: U, pattern: Pattern<U, T>): T {
  if((pattern as any)[union.kind]) {
    return (pattern as any)[union.kind](union as U) as T
  }
  return (pattern as any)["_"](union as U) as T
}

type ValueType = Union<{
  String: {value: string},
  Number: {value: number},
  Boolean: {value: boolean},
  Date: {value: Date}
}>

let value: ValueType = {kind: "String", value: "Hello"};

function main(value: ValueType) {
  let test1 = match(value, {
    String: ({value}) => value,
    Number: ({value}) => value.toString(),
    _: (token) => "Unknown"
  });
  console.log(test1);

  let test2 = match<ValueType, string>(value, {
    String: ({value}) => value,
    Number: ({value}) => value.toString(),
    _: ({kind}) => kind
  });
  console.log(test2);
}

πŸ™ Actual behavior

grafik

Typescript throws an type error

πŸ™‚ Expected behavior

Type should be correctly inferred without explicitly defining the type

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions