[英]TypeScript Generic function return type issue
R
可以是我要定义的任何东西。 ... Promise<R | string>
... Promise<R | string>
不是我的解决方案
错误:(29,9)TS2322:类型'string'无法分配给类型'R'。 “字符串”可分配给类型“ R”的约束,但可以使用约束“ {}”的其他子类型实例化“ R”。
import { isString, } from '@redred/helpers';
interface P {
as?: 'json' | 'text';
body?: FormData | URLSearchParams | null | string;
headers?: Array<Array<string>> | Headers | { [name: string]: string };
method?: string;
queries?: { [name: string]: string };
}
async function createRequest<R> (url: URL | string, { as, queries, ...parameters }: P): Promise<R> {
if (isString(url)) {
url = new URL(url);
}
if (queries) {
for (const name in queries) {
url.searchParams.set(name, queries[name]);
}
}
const response = await fetch(url.toString(), parameters);
if (response.ok) {
switch (as) {
case 'json':
return response.json();
case 'text':
return response.text(); // <- Error
default:
return response.json();
}
}
throw new Error('!');
}
export default createRequest;
我可能会使用重载来表示与调用方的区别……如果调用方指定"text"
则返回类型肯定是Promise<string>
并且该函数不再是R
泛型。
另外:TypeScript命名约定通常为通用类型参数(尤其是T
, U
, K
和P
)保留单字符大写名称,因此我将把P
扩展为Params
。 同样,标识符as
是有问题的,因为它是TypeScript中的保留字,可能会使IDE或编译器感到困惑。 我将取代as
与az
在下面。 好的,所以您的界面是
interface Params {
az?: "json" | "text";
body?: FormData | URLSearchParams | null | string;
headers?: Array<Array<string>> | Headers | { [name: string]: string };
method?: string;
queries?: { [name: string]: string };
}
这是我要使用的重载。 一个非通用的呼叫签名仅接受az
的"text"
,而另一个在R
是通用的,并且仅接受az
的"json"
或undefined
/ missing。 实现签名可以涉及R | string
R | string
或您想要的any
R | string
,因为它在调用方那边是不可见的。
async function createRequest(
url: URL | string,
{ az, queries, ...parameters }: Params & { az: "text" }
): Promise<string>;
async function createRequest<R>(
url: URL | string,
{ az, queries, ...parameters }: Params & { az?: "json" }
): Promise<R>;
async function createRequest<R>(
url: URL | string,
{ az, queries, ...parameters }: Params
): Promise<R | string> {
if (isString(url)) {
url = new URL(url);
}
if (queries) {
for (const name in queries) {
url.searchParams.set(name, queries[name]);
}
}
const response = await fetch(url.toString(), parameters);
if (response.ok) {
switch (az) {
case "json":
return response.json();
case "text":
return response.text(); // <- okay now
default:
return response.json();
}
}
throw new Error("!");
}
这是我们使用它来获取文本的方式:
const promiseString = createRequest("str", { az: "text" }); // Promise<string>
这是我们使用它来获取其他类型的方法(这要求调用者指定R
因为无法推断出它):
interface Dog {
name: string;
age: number;
breed: string;
fleas: boolean;
}
const promiseDog = createRequest<Dog>("dog", {}); // Promise<Dog>
并请注意,如果您已指定R
,则不能要求输入"text"
:
const notGeneric = createRequest<Dog>("dog", {az: "text"}); // error!
// -----> ~~
// "text" is not assignable to "json" or undefined
好的,希望对您有所帮助。 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.