0

Let's say we have some kind of dispatch functions that tries to update a certain prop on an object. Is it possible to have proper type inference in the following scenario?

type EntityA = {
  name: string;
  id: number
}

type EntityB = {
  id: number;
  test1: number;
  test2: string;
  test3: number;
  test4: string;
}

type EntityAction<T> = {
  [K in keyof T]-?:
  | {
    type: 'UPDATE_ENTITY';
    payload: T;
  } |
  {
    type: 'UPDATE_PROP';
    propName: K;
    payload: T[K];
  };
}[keyof T];

function dispatch<T>(action: EntityAction<T>) {
  // omitted logic because it's not relevant
  console.log(action);
}

dispatch<EntityA>({
  type: 'UPDATE_PROP',
  propName: 'name',
});

dispatch<EntityB>({
  type: 'UPDATE_PROP',
  propName: 'test4',
  payload: ''
})

Playground here

I managed to infer the types based on a reply found here (Thanks @jcalz) but as soon as I have more than 1 prop in a type it doesn't work correctly.

Given EntityA, if i dispatch the following:

dispatch<EntityA>({ type: 'UPDATE_PROP',propName: 'id' })

it correctly lets me know that the prop payload is missing However, if I pass

dispatch<EntityA>({ type: 'UPDATE_PROP',propName: 'name' })

It tells me that Type '"name"' is not assignable to type '"id"'. (or whatever the last prop in the type is).

Any idea if this can be "fixed" to properly infer the type of payload? Is it even possible in this setup? It seems to work if EntityAction as:

export type EntityAction<T> = {
  [K in keyof T]-?:
  {
    type: 'UPDATE_PROP';
    propName: K;
    payload: T[K];
  };
}[keyof T];
5
  • 2
    I think it works fine as is. The error message is misleading. If you add the payload property to your first example, the error goes away. Commented Feb 6, 2023 at 9:04
  • Yeah I agree, I was wondering if there's a way to "unconfuse" typescript. Commented Feb 6, 2023 at 12:18
  • 1
    It would probably worth it to open an issue on Github to get this fixed. Commented Feb 6, 2023 at 12:31
  • This looks like ms/TS#46374, a known bug. Does that fully address the question? If so I could write up an answer; if not, what am I missing? Commented Feb 6, 2023 at 18:06
  • Yeah seems to be the same issue. Thanks a lot for your help! Commented Feb 6, 2023 at 20:16

1 Answer 1

1

This looks like a known bug, reported at microsoft/TypeScript#46374, in which an "incomplete" value assigned to a discriminated union yields a compiler error which complains about the wrong property.

It looks like it was introduced in TypeScript 3.9, sometime between [email protected] and [email protected], which leads me to believe that it was probably caused by the work done in microsoft/TypeScript#37589, "Disallow partial matches for discriminant properties when generating error messages", which changed the way discriminated union error messages were generated, fixing a different bug but apparently causing this one.

Anyway, the bug is currently scheduled to be fixed for TypeScript 5.1, but it has been rescheduled several times already, so it's not clear if this will actually happen.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.