繁体   English   中英

TypeScript 条件类型和计算 object 属性名称

[英]TypeScript conditional type and computed object property names

我在将条件类型与计算的 object 属性名称结合使用时遇到问题。 基本上我是根据输入字符串将行插入到数据库中。 然后我根据该输入字符串键入返回 object。 返回 object 中的属性之一是计算名称,它也基于输入字符串。 所以看起来 typescript 将拥有验证这是否正确所需的所有信息,但它一直给我错误。 这是一个非常简化的示例。


//types of the table rows from the database
interface FirstTableRow {
    id: number,
    someFirstRefId: number
};
interface SecondTableRow {
    id: number,
    someSecondRefId: number
};

//maps which table we're working with to its reference column name
const whichToExtraColumn = {
    first: 'someFirstRefId',
    second: 'someSecondRefId'
} as const;

//maps the table to the returned row type
type ConstToObj<T> = (T extends 'first'
    ? FirstTableRow
    : T extends 'second'
    ? SecondTableRow
    : never
);

function createFirstOrSecond<
    T extends keyof typeof whichToExtraColumn
>(
    which: T
): ConstToObj<T> {

    //gets the reference column name for this table
    const refColumn = whichToExtraColumn[which];

    //do database stuff....
    const insertId = 1;

    //build the inserted row
    const test: ConstToObj<T> = {
        id: insertId,
        [refColumn]: 123
    };
    // ^ Type '{ [x: string]: number; id: number; }' is not assignable to type 'ConstToObj<T>'

    return test;

};

我通过对refColumn进行 if-check 来解决此问题,然后根据它生成不同的对象。 但是使用计算属性名称会更容易。 任何帮助,将不胜感激。

您在这里遇到了多个问题:

(1) 计算属性名称被加宽,有人可能会说这是一个错误

type Key = "a" | "b";
let a: Key = Math.random() ? "a" : "b";
const result = { [a]: 1 };
//    -> { [x: string]: number }

因此,您的示例[refColumn]: 123永远不会按照您的意愿行事。

(2) Function 具有泛型参数的函数体没有使用所有可能的子类型进行迭代验证(我猜编译器可能会永远运行),而是使用类型约束验证它们。 因此,如果您有两种泛型类型,而一种是从另一种派生的,则 Typescript 根本不在乎。 通常这不是问题,因为通常一种类型直接是另一种的子类型:

function assign<A extends B, B extends 1 | 2 | 3>(a: A) {
    const b: B = a;
}

您已经创建了一个并非如此的案例,并且约束检查将始终失败。

(3) 不能分配给延迟条件类型。 Typescript 不知道条件类型将采用哪个分支(如果它的评估被延迟),因此只能将any分支分配给它。

function plusOne<A extends 1 | 2>(a: A) {
    const b: (A extends 1 ? 2 : 3) = a + 1;
}

因此,有了这三个限制,基本上不可能在没有手动类型转换的情况下编写 function。 这是为数不多的案例之一, as any看起来都非常合理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM