Typescript 泛型的类型脚本映射

Typescript 泛型的类型脚本映射,typescript,generics,Typescript,Generics,我试图使ObjectType中的每个字段具有自己的泛型,因此每个字段的resolvefn必须返回type属性中定义的类型 type Scalars = { ID: string; Int: number; Float: number; String: string; Boolean: boolean; }; type Field<T extends keyof Scalars> = { type: T, resolve: () => Scalars

我试图使
ObjectType
中的每个
字段
具有自己的泛型,因此每个字段的
resolve
fn必须返回
type
属性中定义的类型

type Scalars = {
  ID: string;
  Int: number;
  Float: number;
  String: string;
  Boolean: boolean;
};

type Field<T extends keyof Scalars> = {
  type: T,
  resolve: () => Scalars[T];
}

type ObjectType<T extends keyof Scalars> = {
  [key: string]: Field<T>
}

const objectType = <T extends keyof Scalars>(config: ObjectType<T>): any => 'todo';

objectType({
  id: {
    type: 'Int',
    // type of `resolve` is `() => (string | number)`, should be `() => number`
    resolve: () => '123',
  },
  name: {
    type: 'String',
    // should be `() => string`
    resolve: () => 123,
  },
});
类型标量={
ID:字符串;
Int:数字;
浮点数;
字符串:字符串;
布尔型:布尔型;
};
类型字段={
类型:T,
解析:()=>标量[T];
}
类型ObjectType={
[键:字符串]:字段
}
const objectType=(配置:objectType):any=>'todo';
对象类型({
身份证:{
键入:“Int”,
//“resolve”的类型为“()=>(字符串|编号)`,应为“()=>编号`
解析:()=>“123”,
},
姓名:{
键入:“字符串”,
//应该是“()=>字符串`
解析:()=>123,
},
});
在调查了其他一些SO问题后,我找到了一个解决方案,几乎解决了我的问题

这是TS操场,我尝试了上面的建议


但是,当我尝试将
推断p
类型传递给扩展了大量标量的泛型时,它失败了。您的
字段
类型可能会形成这样的类型:

type Fields = { [K in keyof Scalars]: Field<K> }[keyof Scalars];
其中,联合体中的所有术语都有一个通用的
类型
字符串文本类型字段,可用于区分它们。这很好,因为这意味着您的
objectType()
方法可能涉及的泛型跳转要少得多,因为
config
属性值可以约束到特定的类型
字段

const objectType = <T extends Record<keyof T, Fields>>(config: T): any => 'todo';
这就是当你做错的时候会发生的事情:

objectType({
  id: { // error! number is not assignable to string
    type: 'String',
    resolve: () => 123,
  },
  ide: { // error! string is not assignable to boolean
    type: 'Boolean',
    resolve: () => "123",
  },
});
这些就是你期望的错误,对吗


看起来您的
字段类型可以形成这样的一种类型:

type Fields = { [K in keyof Scalars]: Field<K> }[keyof Scalars];
其中,联合体中的所有术语都有一个通用的
类型
字符串文本类型字段,可用于区分它们。这很好,因为这意味着您的
objectType()
方法可能涉及的泛型跳转要少得多,因为
config
属性值可以约束到特定的类型
字段

const objectType = <T extends Record<keyof T, Fields>>(config: T): any => 'todo';
这就是当你做错的时候会发生的事情:

objectType({
  id: { // error! number is not assignable to string
    type: 'String',
    resolve: () => 123,
  },
  ide: { // error! string is not assignable to boolean
    type: 'Boolean',
    resolve: () => "123",
  },
});
这些就是你期望的错误,对吗


这确实有效!但我可能应该给出完整的上下文,因为类型有点复杂。
type
属性不能只接受标量,它还可以接受另一个ObjectType,如果它接受ObjectType,resolve函数应该向ObjectType返回一个泛型I传递。这里有一个指向playway bit.ly/3dDlNsJ的短链接(因此抱怨短链接,TS playway link太长,无法发表评论)。我不太倾向于费力地阅读该代码,因为
字段
定义是一组繁琐的嵌套条件类型。如果你让它更简单,我会看一看。公平,我想这次我会给出完整的上下文,但这不是必要的,这里是新的游乐场链接bit.ly/2T6HWUH对你的用例有效吗?(尚未看到新链接)这是因为
resolve
type
为ObjectType时返回的值不是其字段的类型,而是将传递给ObjectType的泛型。也许它可以默认为未传递泛型时的字段类型,这就是某些LIB的做法,但非常重要的是,使用者能够将任意类型传递给ObjectType,该类型将用作ObjectType字段的resolve fn的第一个参数,并且在将此ObjectType用作
类型时用作字段
resolve
fn的返回类型。这确实有效!但我可能应该给出完整的上下文,因为类型有点复杂。
type
属性不能只接受标量,它还可以接受另一个ObjectType,如果它接受ObjectType,resolve函数应该向ObjectType返回一个泛型I传递。这里有一个指向playway bit.ly/3dDlNsJ的短链接(因此抱怨短链接,TS playway link太长,无法发表评论)。我不太倾向于费力地阅读该代码,因为
字段
定义是一组繁琐的嵌套条件类型。如果你让它更简单,我会看一看。公平,我想这次我会给出完整的上下文,但这不是必要的,这里是新的游乐场链接bit.ly/2T6HWUH对你的用例有效吗?(尚未看到新链接)这是因为
resolve
type
为ObjectType时返回的值不是其字段的类型,而是将传递给ObjectType的泛型。也许它可以默认为未传递泛型时的字段类型,这就是某些LIB的做法,但非常重要的是,使用者能够将任意类型传递给ObjectType,该类型将用作ObjectType字段的resolve fn的第一个参数,并且在将此ObjectType用作
类型时用作字段
resolve
fn的返回类型。