Skip to content

Bad inference when passing a field of a discriminated union as field function instead of arrow functionΒ #52798

Closed
@paoloricciuti

Description

@paoloricciuti

Bug Report

πŸ”Ž Search Terms

discriminated union function

⏯ Playground Link

Playground link

πŸ’» Code

import React from "react";

//three random types, non crucial for this example
type A = {
  a: boolean,
}

type B = {
  b: string,
}

type C = {
  c: number;
}

//this is the animations props i'm taking in. is a record of keys and an object composed of
// {value: number} and a discriminated union. If kind = "a" you you have to pass A fields
// and optionally a function that returns a partial of A.
type Animations = {
  [key: string]: ({ value: number } & (
    { kind: "a", func?(): Partial<A> } & A |
    { kind: "b", func?(): Partial<B> } & B |
    { kind: "c", func?(): Partial<C> } & C
  ))
}

type StyleParam<T extends Animations> = Record<keyof T, string>;

//the props of the component...it take animations T and a function that takes
//a Record with all the keys of T and strings.
type AnimatedViewProps<T extends Animations> = {
  style: (
    animationsValues: StyleParam<T>
  ) => string;
  animations: T;
};

const Component = <T extends Animations>({ animations, style }: AnimatedViewProps<T>) => <></>

const App = () => {
  return <>
    <Component animations={{
      test: {
        kind: "a",
        value: 1,
        a: true,
      }
    }}
      style={(anim) => {
              //^?
        //here has you can see i get a narrower type
        return ""
    }} />
    <Component animations={{
      test: {
        kind: "a",
        value: 1,
        a: true,
        //but as soon as i add this func
        func(){
          return {
            a: true,
          }
        }
      }
    }}
      style={(anim) => {
              //^?
        //i get a wider generic type
        return ""
    }} />
    <Component animations={{
      test: {
        kind: "a",
        value: 1,
        a: true,
        //but if the function is an arrow function
        func: ()=>{
          return {
            a: true,
          }
        }
      }
    }}
      style={(anim) => {
              //^?
        //is once again a narrower type
        return ""
    }} />
  </>
} 

πŸ™ Actual behavior

If i pass func as a field function the type inference gets lost

πŸ™‚ Expected behavior

It should not matter if the function is passed as an arrow function or as a normal function

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs InvestigationThis issue needs a team member to investigate its status.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions