English 中文(简体)
通用型号的字句
原标题:Reference inferred literal type from generic type
  • 时间:2024-01-11 14:05:37
  •  标签:
  • typescript

我想界定一个类型<代码>NodeDef,在图表执行框架中界定一个术语。 每一<代码>NodeDef都有<代码>,即,其编号为> /code>,其依据是(其投入)和功能代码,根据投入计算其产出。

我想将<代码>compute功能的参数限制为与deps下指明的地字体相同的物体:

type Nodes = {
    a: number;
    b: number;
    c: string;
};

type Node = keyof Nodes;

type NodeDef<N extends Node, D extends Node> = {
    name: N;
    deps: D[];
    compute: (deps: { [K in D]: Nodes[K] }) => Nodes[N];
};

type Graph = {
    [K in Node]?: NodeDef<K, Node>;
};

然而,在我制作图表时,没有适当提供计算职能的类型:

const config: Graph = {
    a: {
        name:  a ,
        deps: [ b ],
        compute: ({ b, c }) => { // <--  c  shouldn t exist here
            return 2 * b + c.length; 
        },
    },
};

我预计推断的类型是:

(property) compute: (deps: {
    b: number;
}) => number

然而:

(property) compute: (deps: {
    a: number;
    b: number;
    c: string;
}) => number

我怎么能够使型号代谢意我想要的那类方式?

问题回答

页: 1 类型Node ,作为D,在其NodeDef<N, D> ,因此,每个代码的不动产显然取决于所有节点。 如果这不是你想要的话,那么你就需要找到一种办法,以更具体地为<代码>pl。 D类型论点。 最好能写上<代码>Graph,以便每个财产为union, Nodef<K, D> foremevery possible</code>,但该联盟的规模与密码中可比较迅速使用的编号

因此,您将希望Graph,以便自己成为generic ,并作代表的一类论点。 D 每一财产的类型。 因此,应当有<代码>Graph<D>和K,载于keyof D, 财产的类型应为Nodef<K, D[K]>。 与此类似:

type Graph<D extends Record<keyof D, Node>> = {
  [K in Node & keyof D]: NodeDef<K, D[K]>
};

在技术上可以做到:<代码> D有钥匙不在Node之内,但因intersection > > with Node而将这些钥匙排除在结果之外。


现在,你可以给你一个名字,但需要人工(

const config: Graph<{ a: "b" }> = {
  a: {
    name:  a ,
    deps: [ b ],
    compute: ({ b, c }) => { // error
      // --------> ~
      // Property  c  does not exist on type  { b: number; } .
      return 2 * b + c.length;
    },
  },
};

这确实与你一样奏效,但你又被迫写上<条码>{a:“b”}。 如果类型可以简单地描述一般类型的论据,但可以 t。 http://www.un.org/Depts/DGACM/index_french.htm 因此,你可以提供一种称为<条码>的助手功能,即<条码>

const config = graph({
  a: {
    name:  a ,
    deps: [ b ],
    compute: ({ b, c }) => { // error
      // --------> ~
      // Property  c  does not exist on type  { b: number; } 
      return 2 * b + c.length;
    },
  },
});
config;
// ^? const config: Graph<{ a: "b" }>

因此,现在的<代码>config 被推定为类型Graph<{a:“b><>>/code>, 仅依据对的论证。 我们现在必须做的是界定<条码>(<>>>>>。


Here s one approach:

const graph = <const D extends Record<keyof D, Node>>(
  g: { [K in keyof D]: K extends Node ? NodeDef<K, D[K]> : never }
): Graph<D> => g;

TypeScript generic inference is a little tricky; it is possible to infer D from a mapped type over the keys of D (i.e., if it s a homomorphic mapped type, see What does "homomorphic mapped type" mean? for more info). So it has to be in keyof D and not in Node & keyof D. So I moved the "and Node" restriction to the property type, making it the conditional type K extends Node? NodeDef<K, D[K]> : never. Any key in keyof D that does not appear in Node will be mapped to never, and you ll get an error.

Playground link to code





相关问题
store data in memory with nestjs

I am trying to persist some data in my nestjs server so I can then use that data in my client app through http requests. I have created a products.service.ts file with the function getAllData() that ...

React Hook Form Error on custom Input component

I am having a problem when I use react hook form + zod in my application, in short the inputs never change value and I get the following error in the console: Warning: Function components cannot be ...

Updatable promises using proxy in JavaScript

EDIT: I ve updated this question, and the old question is moved here. A POC can be found on this jsfiddle or the snippet below GOAL: The goal here is to make or rather simulate a promise that can be ...