You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中如何通过typeof实现类型窄化?解决特定类型函数调用报错

解决TypeScript中联合类型属性排序时的类型守卫失效问题

你的问题核心在于:sortBy是"sortFoo" | "sortBar"的联合类型,TypeScript无法在回调函数中将typeof arg[sortBy]的运行时检查与sortBy的具体值关联起来,导致arg[sortBy]始终被推断为string | number,因此调用toLowerCase()会触发类型错误。

解决方案:用泛型绑定属性键的具体类型

将排序函数改造成接收sortBy参数的泛型函数,让TypeScript能根据传入的属性键,精确推断出对应属性的类型,此时typeof类型守卫就能正常工作:

interface ObjectProps {
    sortFoo: string,
    sortBar: number
}

const getSortKey = (): "sortFoo" | "sortBar" => {
    // 示例实现
    return Math.random() > 0.5 ? "sortFoo" : "sortBar";
};

const getArrayOfObjects = (): ObjectProps[] => {
    // 示例实现
    return [
        { sortFoo: "Apple", sortBar: 3 },
        { sortFoo: "banana", sortBar: 1 },
        { sortFoo: "Cherry", sortBar: 2 }
    ];
};

// 泛型排序函数,K绑定具体的属性键类型
const sortList = <K extends keyof ObjectProps>(sortBy: K) => {
    return (a: ObjectProps, b: ObjectProps): number => {
        const valA = a[sortBy];
        const valB = b[sortBy];

        // 针对字符串类型做小写转换后比较
        if (typeof valA === "string" && typeof valB === "string") {
            return valA.toLowerCase().localeCompare(valB.toLowerCase());
        }
        // 针对数字类型直接比较
        if (typeof valA === "number" && typeof valB === "number") {
            return valA - valB;
        }
        // 处理混合类型的边界情况(根据需求调整)
        return 0;
    };
};

const sortBy: "sortFoo" | "sortBar" = getSortKey();
const objects: ObjectProps[] = getArrayOfObjects().sort(sortList(sortBy));

为什么原来的写法不行?

在你最初的代码中,sortBy是联合类型,TypeScript无法在map回调里推断出:当typeof arg[sortBy] === 'string'时,sortBy一定是"sortFoo"(对应字符串属性)。因此arg[sortBy]的类型始终是string | number,TypeScript不允许你在可能为数字的值上调用toLowerCase()。

备选方案:类型断言(不推荐)

如果你不想重构函数,也可以用类型断言跳过TypeScript的检查,但这种方法不安全(如果后续属性类型或sortBy的范围变化,容易引入bug):

const sortList = (...args: ObjectProps[]): number => {
    const compare: (string | number)[] = args.map(
        (arg: ObjectProps): string | number => 
            typeof arg[sortBy] === 'string' ? (arg[sortBy] as string).toLowerCase() : arg[sortBy]
    );

    return compare[0] < compare[1] ? -1 : 1;
};

内容的提问来源于stack exchange,提问作者colin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:03:37