将对象文字指定给typescript泛型类型

将对象文字指定给typescript泛型类型,typescript,typescript-generics,Typescript,Typescript Generics,我正在构建一个FormConditions接口,其中我将有一个带有任意键的对象,每个键都是实现Condition接口的类的实例。我想将这个对象文本分配给一个变量,并使结果对象的类型a)只响应对象文本中的键,B)考虑每个键可能具有的任何子类或其他扩展 如果您检查下面的代码,我可以让所有实际类型都正常工作。我遇到的问题是,如果不显式声明每个键的子类型,我不知道如何直接将对象分配给变量。相反,我可以通过identity函数makeFormConditions传递它,该函数使用泛型来正确推断结果对象的类

我正在构建一个
FormConditions
接口,其中我将有一个带有任意键的对象,每个键都是实现
Condition
接口的类的实例。我想将这个对象文本分配给一个变量,并使结果对象的类型a)只响应对象文本中的键,B)考虑每个键可能具有的任何子类或其他扩展

如果您检查下面的代码,我可以让所有实际类型都正常工作。我遇到的问题是,如果不显式声明每个键的子类型,我不知道如何直接将对象分配给变量。相反,我可以通过identity函数
makeFormConditions
传递它,该函数使用泛型来正确推断结果对象的类型。这是做这件事的唯一方法还是有直接分配的方法?您可以随意更改
FormCondition
的定义,以完成此任务

接口条件{
名称:string
身份证号码
}
类型FormConditions={
[P in keyof T]:T[P]
}
类SimpleCondition实现条件{
构造函数(公共名称:字符串,公共id:number){}
}
类ListCondition实现条件{
构造函数(public name:string,public id:number,public entries:T[]){}
}
//这是一个传递函数,仅用于使类型正常工作
函数makeFormConditions(obj:T):FormConditions{
返回obj;
}
//希望避免函数调用以使类型正常工作
const conditions=makeFormConditions({
simpleOne:新的SimpleCondition('simpleOne',1),
simplewo:新的SimpleCondition('simplewo',2),
列表:新的列表条件('list',3,['foo',bar'])
})
//这是可行的,但冗余冗长
//常量条件:FormConditions={
//simpleOne:新的SimpleCondition('simpleOne',1),
//simplewo:新的SimpleCondition('simplewo',2),
//列表:新的列表条件('list',3,['foo',bar'])
// }
//
//而是宁愿不使用该函数或
//有关类型声明的具体信息:
//常量条件:FormConditions={
//simpleOne:新的SimpleCondition('simpleOne',1),
//simplewo:新的SimpleCondition('simplewo',2),
//列表:新的列表条件('list',3,['foo',bar'])
// }
条件.列表.名称
条件.列表.条目
conditions.simpleOne.name
conditions.simpleOne.entries//错误,如预期

以下是对上述问题的解答。

简短回答:否,您不能分配包含异类类型的对象文字,也不能维护泛型类型约束。需要一个受约束的辅助函数(当前实现的)

扩展接口
条件
以包括所有子类型属性
条件
的定义可以扩展为接受可选的
条目
数组,这样
FormConditions
可以同时保存
SimpleConditions
listcditions
。这会产生不希望出现的副作用,
SimpleCondition
的实例可能会引用缺少的
条目
属性而不会出错

interface Condition<E> {
    name: string
    id: number
    entries?: E[]
}

type FormConditions<E, T extends Record<string, Condition<E>>> = {
    [P in keyof T]: T[P]
}

class SimpleCondition<E = never> implements Condition<E> {
    constructor(public name: string, public id: number) {}
}

class ListCondition<E> implements Condition<E> {
    constructor(public name: string, public id: number, public entries: E[]) {}
}

const conditions: FormConditions<string, Record<string, Condition<string>>> = {
    simpleOne: new SimpleCondition('simpleOne', 1),
    simpleTwo: new SimpleCondition('simpleTwo', 2),
    list: new ListCondition('list', 3, ['foo', 'bar'])
}

conditions.list.name;
conditions.list.entries;
conditions.simpleOne.name;
conditions.simpleOne.entries;  // Expected error; however, no error, since `entries` is optional parameter.

看起来您已经用尽了我所知道的选择:要么显式注释类型,要么让类型被推断。如果希望推断的类型符合约束,则需要类似于受约束的泛型辅助函数的函数,就像处理
makeFormConditions()
一样。这里我唯一要更改的是从中返回类型
T
,而不是
FormConditions
,这基本上是不允许的。
interface Condition {
    name: string
    id: number
}

type FormConditions<E, T extends Record<string, Condition>> = {
    [P in keyof T]: T[P]
}

class SimpleCondition<E = never> implements Condition {
    constructor(public name: string, public id: number) {}
}

class ListCondition<E> implements Condition {
    constructor(public name: string, public id: number, public entries: E[]) {}
}

const conditions: FormConditions<string, Record<string, Condition>> = {
    simpleOne: new SimpleCondition('simpleOne', 1),
    simpleTwo: new SimpleCondition('simpleTwo', 2),
    list: new ListCondition('list', 3, ['foo', 'bar'])
}

conditions.list.name;
conditions.list.entries; // Error: Property 'entries' does not exist on type 'Condition'.
conditions.simpleOne.name;
conditions.simpleOne.entries; // error (as expected - Good)