首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TypeScript条件类型和计算对象属性名称

TypeScript条件类型和计算对象属性名称
EN

Stack Overflow用户
提问于 2021-04-12 23:41:27
回答 1查看 331关注 0票数 0

我在结合使用条件类型和计算对象属性名称时遇到了问题。基本上,我是根据输入字符串在数据库中插入行。然后,我根据输入字符串输入返回对象。返回对象中的一个属性是也基于输入字符串的计算名称。因此,看起来typescript已经有了验证它是否正确所需的所有信息,但它总是给我错误。这是一个非常简单的例子。

代码语言:javascript
复制
//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,然后根据它生成不同的对象。但是使用计算属性名称会容易得多。任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-13 01:42:56

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

(1)计算属性名称被加宽,可以说是this is a bug

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

因此,在您的示例中,[refColumn]: 123永远不会像您希望的那样运行。

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

代码语言:javascript
复制
function assign<A extends B, B extends 1 | 2 | 3>(a: A) {
    const b: B = a;
}

您已经创建了一个情况并非如此,并且约束检查总是会失败。

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

代码语言:javascript
复制
function plusOne<A extends 1 | 2>(a: A) {
    const b: (A extends 1 ? 2 : 3) = a + 1;
}

因此,有了这三个限制,如果不进行手动类型转换,基本上就不可能编写函数。这是为数不多的as any似乎非常合理的案例之一。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67061394

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档