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

TypeScript泛型接口数组赋值报错,如何存储任意Living类型的Speaker?

TypeScript泛型Speaker数组类型不兼容问题解决

错误原因

你遇到的报错是TypeScript函数参数逆变特性导致的类型安全拦截:

  • Speaker<Living>类型要求其speak方法可以接收任意Living类型(包括Person和Dog)作为参数
  • 你定义的michel是Speaker<Person>类型,它的speak方法只能接收Person类型参数,如果强行塞到Speaker<Living>数组中,后续给speak传入Dog参数时就会出现运行时错误,因此TS提前抛出了类型报错。

解决方案

根据不同的使用场景可以选择以下三种实现方式:

场景1:数组需要混装所有Living子类型的Speaker,调用时可自行保证参数类型匹配

用分发条件类型生成允许所有子类型Speaker的联合类型,无需修改原有Speaker定义:

interface Dog {
  legs: number;
}

interface Person {
  arms: number;
}

type Living = Person | Dog;

interface Speaker<T extends Living> {
  speak: (living: T) => void;
};

// 新增:生成所有Living子类型对应的Speaker联合
type AnySpeaker<T extends Living = Living> = T extends unknown ? Speaker<T> : never;

const michel: Speaker<Person> = { speak: (person) => console.log(`I have ${person.arms} arms`) };

// 数组类型改为AnySpeaker即可混装所有子类型Speaker
const speakers: Array<AnySpeaker> = [michel];

场景2:Speaker设计上支持接收任意Living类型参数

将泛型定义从Speaker接口移到speak方法上:

interface Dog {
  legs: number;
}

interface Person {
  arms: number;
}

type Living = Person | Dog;

// 泛型改在speak方法上
interface Speaker {
  speak: <T extends Living>(living: T) => void;
};

const michel: Speaker = { 
  speak: (living) => console.log(`I have ${(living as Person).arms} arms`) 
};

const speakers: Array<Speaker> = [michel];

场景3:需要统一传入任意Living参数调用数组中的Speaker,保证运行时安全

给Living类型加标识字段,调用时先做类型匹配再执行方法:

interface Dog {
  type: 'dog',
  legs: number;
}

interface Person {
  type: 'person',
  arms: number;
}

type Living = Person | Dog;

interface Speaker<T extends Living> {
  matchType: T['type'],
  speak: (living: T) => void;
};

const michel: Speaker<Person> = { 
  matchType: 'person',
  speak: (person) => console.log(`I have ${person.arms} arms`) 
};

const speakers: Array<Speaker<Living>> = [michel];

// 统一调用方法,自动匹配对应Speaker
function invokeSpeaker(speaker: Speaker<Living>, living: Living) {
  if (speaker.matchType === living.type) {
    speaker.speak(living as never);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 10:24:04