如何基于入参选项对象中的布尔标识收窄TypeScript函数返回值类型?
让TypeScript根据布尔参数推断函数返回类型的解决方案
你的问题核心在于TypeScript无法将options.raw的具体布尔值与函数返回类型建立关联,导致返回类型被推断为Promise<RawResponse | string[]>,进而调用map时出现类型错误。以下两种方案可以解决这个问题:
方案一:泛型结合条件类型
通过给Option类型添加泛型参数,将raw的具体值与返回类型绑定:
type Option<T extends boolean = boolean> = { param: string raw?: T otherParam?: string; } type RawResponse = { message: string data: string[] } function fakeFetch() { return Promise.resolve({ message: "Hello", data: ["test1", "test2"] } as RawResponse) } async function foo<T extends boolean = boolean>(options: Option<T>): Promise<T extends true ? RawResponse : string[]> { const response = await fakeFetch() if (options.raw) { return response as T extends true ? RawResponse : string[] } return response.data as T extends true ? RawResponse : string[] }
调用示例
// raw: false 时,返回类型自动推断为 Promise<string[]>,可正常调用map foo({param: "test", raw: false}).then(results => { results.map(result => console.log(result)) }); // raw: true 时,返回类型自动推断为 Promise<RawResponse> foo({param: "test", raw: true}).then(results => { console.log(results.message) }); // 不传入raw时,返回类型为 Promise<RawResponse | string[]>,需手动做类型守卫 foo({param: "test"}).then(results => { if ('message' in results) { console.log(results.message) } else { results.map(r => console.log(r)) } });
方案二:函数重载
通过定义多个函数重载签名,明确不同raw值对应的返回类型:
type Option = { param: string raw?: boolean otherParam?: string; } type RawResponse = { message: string data: string[] } function fakeFetch() { return Promise.resolve({ message: "Hello", data: ["test1", "test2"] } as RawResponse) } // 重载签名:raw为true时返回RawResponse的Promise function foo(options: Option & { raw: true }): Promise<RawResponse>; // 重载签名:raw为false时返回string[]的Promise function foo(options: Option & { raw: false }): Promise<string[]>; // 重载签名:不传入raw时返回联合类型的Promise function foo(options: Option): Promise<RawResponse | string[]>; // 函数实现 async function foo(options: Option) { const response = await fakeFetch() if (options.raw) { return response } return response.data }
调用示例
foo({param: "test", raw: false}).then(results => { results.map(result => console.log(result)) // 类型推断正确,无报错 }); foo({param: "test", raw: true}).then(results => { console.log(results.message) // 正确识别为RawResponse类型 });
原代码问题说明
原代码中Option的raw是可选布尔类型,TypeScript无法将调用时传入的raw具体值(true/false)与函数返回类型做关联,因此返回类型只能推断为Promise<RawResponse | string[]>,调用map时因为RawResponse没有该方法,所以触发类型错误。
内容的提问来源于stack exchange,提问作者Mathieu Rousseau
相关产品推荐
相关产品推荐

