TypeScript中能否定义关联参数与响应的联合类型并复用?
如何在TypeScript中复用ResponseMap实现输入参数到输出类型的精确映射?
你遇到的问题是原有的泛型写法无法让TypeScript精确推断出输入路径对应的响应类型,导致返回类型变成了所有可能响应的联合类型。要复用ResponseMap同时实现精确的类型映射,有两种可行方案:
方案1:将ResponseMap重构为索引类型(推荐)
把原来的联合类型改成键值对形式的索引类型,更符合"路径-响应类型"的映射逻辑,TypeScript也能更轻松地做精确推断:
// 定义索引类型的ResponseMap,路径作为键,响应类型作为值 type ResponseMap = { "/user/": UserData; "/posts/": PostData; }; // 泛型约束路径为ResponseMap的键,返回对应的值类型 async function getRequest<Path extends keyof ResponseMap>( path: Path ): Promise<ResponseMap[Path] | undefined> { const response = await fetch(path); return response.json(); } // 此时类型推断正确,不会报错 const response: UserData | undefined = await getRequest("/user/");
这种方式的优势是直观易懂,而且ResponseMap可以直接在其他函数中复用:
// 复用ResponseMap的POST请求函数 async function postRequest<Path extends keyof ResponseMap>( path: Path, payload: Partial<ResponseMap[Path]> ): Promise<ResponseMap[Path]> { const response = await fetch(path, { method: "POST", body: JSON.stringify(payload), headers: { "Content-Type": "application/json" } }); return response.json(); }
方案2:保留联合类型,用Extract条件类型提取对应项
如果你想保留原来的联合类型结构,可以通过Extract条件类型从ResponseMap中提取对应路径的响应类型:
// 保留原有的联合类型ResponseMap type ResponseMap = { requestPath: "/user/", response: UserData } | { requestPath: "/posts/", response: PostData }; // 定义条件类型,根据路径提取对应的响应类型 type ResponseForPath<Path extends ResponseMap["requestPath"]> = Extract<ResponseMap, { requestPath: Path }>["response"]; // 泛型约束路径为ResponseMap中的requestPath,返回提取出的响应类型 async function getRequest<Path extends ResponseMap["requestPath"]>( path: Path ): Promise<ResponseForPath<Path> | undefined> { const response = await fetch(path); return response.json(); } // 类型推断正确,无报错 const response: UserData | undefined = await getRequest("/user/");
这种方案也能实现类型精确推断,并且ResponseMap同样可以在其他需要路径-响应映射的地方复用。
为什么原代码会报错?
原代码中Value extends ResponseMap的泛型约束,当传入具体路径时,TypeScript无法确定Value是联合类型中的哪一项,因此会将Value["response"]推断为所有可能响应类型的联合(UserData | PostData),导致返回类型和你期望的单一类型不匹配,从而报错。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

