类型'string'不能分配给类型'“ foo”'

时间:2018-10-07 15:18:02

标签: typescript

我有此代码:

const baseUpstreamImpl = (
  client: IClient,
): ProtocolExtension<
  {
    foobar: (buff: Buffer) => Promise<string>;
  }
> => ({
  name: 'base upstream impl',
  type: 'upstream',
  messageCreators: {
    foobar: (buff: Buffer)  =>
      Promise.resolve({
        type: 'foobar',
        payload: buff,
      }),
  },
});

这个。是我对foobar函数的错误:

[ts]
Type '(buff: Buffer) => Promise<{ type: string; payload: Buffer; }>' is not assignable to type '(...args: any[]) => Promise<IMessage<{ foobar: (buff: Buffer) => Promise<string>; }, "foobar">>'.
  Type 'Promise<{ type: string; payload: Buffer; }>' is not assignable to type 'Promise<IMessage<{ foobar: (buff: Buffer) => Promise<string>; }, "foobar">>'.
    Type '{ type: string; payload: Buffer; }' is not assignable to type 'IMessage<{ foobar: (buff: Buffer) => Promise<string>; }, "foobar">'.
      Types of property 'type' are incompatible.
        Type 'string' is not assignable to type '"foobar"'.
baseUpstreamImpl.ts(11, 5): The expected type comes from property 'foobar' which is declared here on type '{ foobar: (...args: any[]) => Promise<IMessage<{ foobar: (buff: Buffer) => Promise<string>; }, "foobar">>; }'
(property) foobar: (...args: any[]) => Promise<IMessage<{
    foobar: (buff: Buffer) => Promise<string>;
}, "foobar">>

这是我的类型:

type EnforcePromise<T, P = any> = T extends Promise<P> ? T : Promise<T>;

type Promised<T> = {
  [P in keyof T]: (...args: InferArgs<T[P]>) => EnforcePromise<InferType<T[P]>>
};

type Filter<T, Cond, U extends keyof T = keyof T> = {
  [K in U]: T[K] extends Cond ? K : never
}[U];

type EventKey<T> = Filter<T, (...args: any[]) => any>;


interface IMessage<T, K extends EventKey<T> = EventKey<T>> {
  type: K;
  payload: InferArgs<T[K]>;
}


export interface ProtocolExtension<T, U, R = {}> {
  name: string;
  type: 'upstream' | 'downstream';
  handlers: Promised<T>;
  messageCreators: {
    [K in keyof U]: (
      ...args: any[]
    ) => Promise<IMessage<U>>
  };
}

1 个答案:

答案 0 :(得分:1)

代码中存在两个问题,都与打字稿推断文字类型的方式有关。

第一个(以及您收到的错误消息)是type: 'foobar'会推断typestring的事实(在没有直接理由将其推断为字符串文字类型'foobar')。解决方案是手动将类型断言用于字符串文字类型。

解决此问题后,有效负载出现新错误。 payload应该是InferArgs<T[K]>,因此它应该是带有函数参数的元组。您只为其分配一个值。如果我们要写[buf],我们将遇到与上面的字符串文字类型问题类似的问题。也就是说,数组文字将被键入为数组而不是元组(同样在没有直接理由将其键入为元组类型的情况下)。

还有第三个问题,即缺少handelrs属性,但是泰铢可能只是一个疏忽。

const baseUpstreamImpl = (
    client: {},
): ProtocolExtension<
{},
{
    foobar: (buff: {}) => Promise<string>;
}
> => ({
    name: 'base upstream impl',
    type: 'upstream',
    handlers: null as any,
    messageCreators: {
        foobar: (buff: {}) =>
            Promise.resolve({
                type: 'foobar' as 'foobar',
                payload: [buff] as [{}],
            }),
    },
});