Typescript: 泛型,在给定键时推断对象的值

huangapple go评论68阅读模式
英文:

Typescript: Generics, infer the value of object if key is given

问题

以下是您要翻译的内容:

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: ''
})

以下是代码的翻译部分:

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: ''
})
英文:

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&lt;T&gt; = {
  [K in keyof T]-?:
  | {
    type: &#39;UPDATE_ENTITY&#39;;
    payload: T;
  } |
  {
    type: &#39;UPDATE_PROP&#39;;
    propName: K;
    payload: T[K];
  };
}[keyof T];

function dispatch&lt;T&gt;(action: EntityAction&lt;T&gt;) {
  // omitted logic because it&#39;s not relevant
  console.log(action);
}

dispatch&lt;EntityA&gt;({
  type: &#39;UPDATE_PROP&#39;,
  propName: &#39;name&#39;,
});

dispatch&lt;EntityB&gt;({
  type: &#39;UPDATE_PROP&#39;,
  propName: &#39;test4&#39;,
  payload: &#39;&#39;
})

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&lt;EntityA&gt;({ type: &#39;UPDATE_PROP&#39;,propName: &#39;id&#39; })

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

dispatch&lt;EntityA&gt;({ type: &#39;UPDATE_PROP&#39;,propName: &#39;name&#39; })

It tells me that
Type &#39;&quot;name&quot;&#39; is not assignable to type &#39;&quot;id&quot;&#39;. (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&lt;T&gt; = {
  [K in keyof T]-?:
  {
    type: &#39;UPDATE_PROP&#39;;
    propName: K;
    payload: T[K];
  };
}[keyof T];

答案1

得分: 1

这似乎是一个已知的问题,报告在microsoft/TypeScript#46374,其中给辨别联合分配一个“不完整”的值会导致编译器错误,抱怨有关错误属性。

看起来它是在TypeScript 3.9中引入的,大约在typescript@3.9.0-dev.20200328typescript@3.9.0-dev.20200407之间,这让我相信它可能是由microsoft/TypeScript#37589中的工作引起的,该工作“在生成错误消息时不允许部分匹配辨别属性”,更改了辨别联合错误消息的生成方式,修复了不同的错误,但显然引起了这个错误。

无论如何,这个问题当前计划在TypeScript 5.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 typescript@3.9.0-dev.20200328 and typescript@3.9.0-dev.20200407, 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.

huangapple
  • 本文由 发表于 2023年2月6日 16:06:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75358725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定