TypeScript联合类型函数调用报错原因及外部类型优化咨询
TypeScript联合函数类型调用报错原因及优化方案
错误原因
当你用|将TGetCharacters和TGetCharacter两个函数类型联合成TFnGetData时,TypeScript对联合函数的调用遵循参数逆变规则:调用时必须传入所有函数类型都能接受的参数。TGetCharacters不需要参数,但TGetCharacter强制要求传入一个number类型的id,所以联合后的TFnGetData会要求调用时必须传number参数——哪怕你在函数实现里把id设为可选,TS也会以外部定义的联合类型规则来检查调用,这就是报错的核心原因。
优化方案(外部定义类型前提下)
方案1:使用函数重载类型替代联合类型
这是最贴合需求的方案,重载类型能明确区分不同调用签名的返回值:
// 外部定义重载函数类型 type TFnGetData = { (): Promise<TArrayResponse|null>; (id: number): Promise<TCharacter|null>; }; // 实现函数 const getCharacters: TFnGetData = (id?: number) => { if (id !== undefined) { // 单个角色查询逻辑 return Promise.resolve({ id, name: "Alice" } as TCharacter); } // 角色列表查询逻辑 return Promise.resolve([{ id: 1, name: "Bob" }] as TArrayResponse); }; // 调用均无报错 getCharacters(); // 返回 Promise<TArrayResponse|null> getCharacters(1); // 返回 Promise<TCharacter|null>
方案2:调整联合类型为带可区分标记的类型
如果必须保留联合类型形态,可以给每个函数类型添加唯一标记,调用前通过类型守卫判断:
// 外部定义带标记的联合类型 type TGetCharacters = { type: "list"; (): Promise<TArrayResponse|null> }; type TGetCharacter = { type: "single"; (id: number): Promise<TCharacter|null> }; type TFnGetData = TGetCharacters | TGetCharacter; // 实现并赋值 const getCharacters: TFnGetData = Object.assign( (id?: number) => { if (id !== undefined) { return Promise.resolve({ id, name: "Alice" } as TCharacter); } return Promise.resolve([{ id: 1, name: "Bob" }] as TArrayResponse); }, { type: "list" } ); // 调用前通过类型守卫匹配签名 if ((getCharacters as TGetCharacters).type === "list") { getCharacters(); // 无报错 } else { getCharacters(1); }
方案3:用可选参数统一函数类型定义
如果允许调整外部类型为单个统一签名,这是最简洁的方式:
// 外部定义带可选参数的函数类型 type TFnGetData = (id?: number) => Promise<TArrayResponse|null | TCharacter|null>; // 实现函数 const getCharacters: TFnGetData = (id?: number) => { if (id !== undefined) { return Promise.resolve({ id, name: "Alice" } as TCharacter); } return Promise.resolve([{ id: 1, name: "Bob" }] as TArrayResponse); }; // 调用均无报错 getCharacters(); getCharacters(1);
内容的提问来源于stack exchange,提问作者Darwin97VA
相关产品推荐
相关产品推荐

