【问题标题】:Object literal may only specify known properties, and 'data' does not exist in type 'PromiseLike<T>'对象字面量只能指定已知属性,并且“PromiseLike<T>”类型中不存在“数据”
【发布时间】:2020-05-15 17:25:04
【问题描述】:

我有一个向服务器发出请求的方法,根据 URL,它可能会返回完全不同形状的数据。

在此之前,我只是将预期的接口转换为返回的对象:

    const data = Promise.resolve(makeSignedRequest(requestParameters));
    return data as Promise<AwesomeResponse>;

但今天我遇到了这种语法,我可以明确地告诉方法我期望什么样的数据:

    const data = Promise.resolve(makeSignedRequest<AwesomeResponse>(requestParameters));
    return data;

现在。 makeSignedRequest 可能会返回AwesomeResponseGreatResponseAmazingResponse 等类型,但所有这些都有一个共同点。它们都共享相同的结构 - BaseResponse 的结构。

我所有的回复都扩展了BaseResponse,所以我们很酷。

说了这么多,TypeScript 还在抱怨下面的代码:

import https from "https";
export interface BaseResponse {
    meta: {};
    data: Array<{}>;
    error?: {
        statusCode: number | undefined;
        statusMessage: string | undefined;
    };
}

export const makeSignedRequest = <T>(url): Promise<T> => {
    return new Promise((resolve, reject) => {
        // create Request with event listeners
        const req = https.request(url, (res) => {
            res.on("end", () => {
                if (res.statusCode !== 200) {
                    resolve({
                        data: [],
                        meta: {},
                        error: {}
                    });
                }
            });
        });
    });
};

resolve({data: [], 被 VS Code 强调,因为正如我在标题中提到的,

Argument of type '{ data: never[]; meta: {}; error: { statusCode: number | undefined; statusMessage: string | undefined; }; }' is not assignable to parameter of type 'T | PromiseLike<T> | undefined'.
Object literal may only specify known properties, and 'data' does not exist in type 'PromiseLike<T>'.

我在这里错过了什么?

【问题讨论】:

标签: node.js typescript


【解决方案1】:

你需要一个generic constraint:

export const makeSignedRequest = < T extends BaseResponse  > ...

和一个类型断言:

      resolve({
        data: [],
        meta: {},
        error: {
          statusCode: res.statusCode,
          statusMessage: res.statusMessage,
        },
      } as T);

此代码适用于我在 TS 3.8.3 的 VSCode 中

export interface BaseResponse {
    data: [];
    meta: {};
    error?: {
        statusCode: number | undefined;
        statusMessage: string | undefined;
    };
}

function makeSignedRequest<T extends BaseResponse>(): Promise<T> {
    return new Promise((resolve, reject) => {
        // create Request with event listener
        resolve({
            data: [],
            meta: {},
            error: {},
        } as T);
    });
}

【讨论】:

  • 不。这会引发一整套新的错误。首先,我需要先将表达式转换为“未知”。例如(与 T 一样未知),然后是 Argument of type 'T' is not assignable to parameter of type '(T extends BaseResponse ? any : any) | PromiseLike&lt;T extends BaseResponse ? any : any&gt; | undefined'. Type 'T' is not assignable to type 'PromiseLike&lt;T extends BaseResponse ? any : any&gt;'.
  • 你用的是什么TS版本?
  • TypeScript 3.8.3
  • 你为什么有T extends BaseResponse ? any : any?应该只是T extends BaseResponse
  • 它不是强制转换,它是一个断言,包括它意味着编译器没有检查实际值。
【解决方案2】:

你是说:你的函数返回一个泛型类型 Promise,所以resolve 只接受 T 作为参数。但是{data: [], meta: {}, error: {}} 不是 T,因为 T 可以是任何东西(字符串、数字 ...),所以它不会编译。您的函数对泛型类型没有意义,它应该返回Promise&lt;BaseReponse&gt;,仅此而已。返回Promise&lt;T&gt;不会产生任何好处

【讨论】:

    猜你喜欢
    • 2021-02-18
    • 2021-09-27
    • 2017-08-10
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 2022-08-24
    • 1970-01-01
    • 2018-09-06
    相关资源
    最近更新 更多