代码之家  ›  专栏  ›  技术社区  ›  Vinz243

类型“string”不可分配给类型“foo”

  •  0
  • Vinz243  · 技术社区  · 6 年前

    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 回复  |  直到 6 年前
        1
  •  1
  •   Titian Cernicova-Dragomir    6 年前

    代码中有两个问题都与typescript推断文本类型的方式有关。

    第一个(以及您收到的错误消息)是 type: 'foobar' 将推断 type string (在没有imediate原因的情况下,将其推断为字符串文字类型 'foobar' ). 解决这个问题的方法是手动使用一个类型断言来声明字符串文本类型。

    修复此问题后,有效负载上出现新错误。 payload 应该是 InferArgs<T[K]> 所以它应该是元组和函数的参数。你只能给它赋值。如果我们要写 [buf] 我们会遇到与上面的字符串文本类型问题类似的问题。也就是说,数组文字将被类型化为数组而不是元组(同样,在没有imediate原因的情况下,将其类型化为元组类型)。

    还有第三个问题,即缺乏 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 [{}],
                }),
        },
    });