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

TypeScript泛型继承接口时抛出属性不存在错误的问题排查

泛型排序方法的类型错误分析与解决

接口定义

A.ts

export interface A {
    requestID: number;
    createdUser: string;
    createdDate: string;
    text: string
}

B.ts

export interface B {
    requestID: number;
    createdUser: string;
    createdDate: string;
    department: string;
    emailID: string;
}

AB.ts

export interface AB extends A, B {
    requestType: string;
    assignedUser: string;
}

出错代码与错误信息

你编写的泛型排序方法如下:

function sort<T extends AB | A | B>(requests: T[], columnName: string) {
    switch columnName {
        case "requestID": {
            requests.sort((a, b) => a.requestID > b.requestID ? 1 : -1);
        } case "requestType": {
            requests.sort((a, b) => a.requestType > b.requestType ? 1 : -1);
            break;
        } case "text": {
            requests.sort((a, b) => a.text > b.text ? 1 : -1);
            break;
        } case "department": {
            requests.sort((a, b) => a.department > b.department ? 1 : -1);
            break;
        }
    }
}

运行时触发错误:

Property 'requestType' does not exist on type 'AB | A | B'.

问题原因

  1. 泛型约束理解偏差:T extends AB | A | B的含义是T是这三个类型中的某一个具体类型,比如T可能是A,也可能是B,并非同时包含三个类型的所有属性。当你在case "requestType"分支访问a.requestType时,TypeScript无法确认当前T是AB类型——如果传入的是A或B类型数组,该属性根本不存在,因此报错。
  2. switch逻辑漏洞:case "requestID"分支未添加break,会导致代码执行完该分支后,继续进入case "requestType"的逻辑,引发额外错误。

解决方案

方案一:类型守卫+类型断言

通过类型守卫判断数组元素是否包含目标属性,再用类型断言明确类型:

function sort<T extends AB | A | B>(requests: T[], columnName: string) {
    switch (columnName) {
        case "requestID":
            requests.sort((a, b) => a.requestID > b.requestID ? 1 : -1);
            break;
        case "requestType":
            // 校验元素是否含requestType属性,确保为AB类型
            if ("requestType" in requests[0]) {
                requests.sort((a, b) => (a as AB).requestType > (b as AB).requestType ? 1 : -1);
            }
            break;
        case "text":
            // 校验是否含text属性,确保为A或AB类型
            if ("text" in requests[0]) {
                requests.sort((a, b) => (a as A | AB).text > (b as A | AB).text ? 1 : -1);
            }
            break;
        case "department":
            // 校验是否含department属性,确保为B或AB类型
            if ("department" in requests[0]) {
                requests.sort((a, b) => (a as B | AB).department > (b as B | AB).department ? 1 : -1);
            }
            break;
    }
}

方案二:泛型关联列名与属性(更简洁优雅)

让列名参数仅能传入当前T类型存在的属性,同时自动根据属性类型处理排序逻辑:

function sort<T extends AB | A | B, K extends keyof T>(requests: T[], columnName: K) {
    requests.sort((a, b) => {
        const valA = a[columnName];
        const valB = b[columnName];
        
        // 数字类型直接做差值比较
        if (typeof valA === "number" && typeof valB === "number") {
            return valA - valB;
        }
        // 字符串类型用localeCompare做自然排序
        else if (typeof valA === "string" && typeof valB === "string") {
            return valA.localeCompare(valB);
        }
        // 其他类型默认不排序
        return 0;
    });
}

该方案优势:

  • 编译阶段就限制列名参数的合法范围,传入不存在的列名会直接报错
  • 无需手动编写多个case分支,自动适配不同属性类型的排序逻辑

内容的提问来源于stack exchange,提问作者ngShravil.py

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:45:23