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

typescript中每个记录值的泛型类型

  •  0
  • Atharva  · 技术社区  · 3 年前

    我有一个这样的对象:

    import zod from 'zod';
    
    const f1 = (params: { a: string }) => ({ b: params.a }); // some function
    const f2 = () => {}; // some function
    
    const dir = {
        // ok
        register: {
            method: f1, // some function
            inputSchema: zod.object({ a: zod.string() }),
            outputSchema: zod.object({ b: zod.string() })
        },
        // not ok
        view: {
            method: f2, // some function
            inputSchema: zod.object({ c: zod.string() }),
            outputSchema: zod.object({ d: zod.string() })
        }
    };
    

    现在,我想在字典上强制执行一个类型,以便方法中函数的参数应该匹配 zod.infer<typeof inputSchema> 和函数的返回值应该匹配 zod.infer<typeof outputSchema>

    我尝试了以下操作,但typescript没有抛出任何错误

    const f1 = (params: { a: string }) => ({ b: params.a }); // some function
    const f2 = () => {}; // some function
    
    interface RecordValue<
        P extends zod.Schema = zod.Schema,
        Q extends zod.Schema = zod.Schema
    > {
        method: (params: zod.infer<P>) => zod.infer<Q>;
        inputSchema: P;
        outputSchema: Q;
    }
    
    const d: { [key: string]: RecordValue } = {
        register: {
            method: f1, // some function
            inputSchema: zod.object({ a: zod.string() }),
            outputSchema: zod.object({ b: zod.string() })
        },
        view: {
            method: f2, // some function
            inputSchema: zod.object({ c: zod.string() }),
            outputSchema: zod.object({ d: zod.string() })
        }
    };
    

    如何强制执行这样的类型?

    0 回复  |  直到 3 年前
        1
  •  1
  •   Dimava    3 年前

    您可以制作一个函数来检查类型,通过推断值类型并将其与正确的类型进行交互: https://tsplay.dev/N5x2Pw

    function EnsureCorrect<
      K extends string,
      const R extends Record<K, RecordValue>
    >(v: R & {
      [K in keyof R]: RecordValue<R[K]['inputSchema'], R[K]['outputSchema']>
    }): asserts v is R { }
    
    const d = EnsureCorrect({
      register: {
        method: f1, // some function
        inputSchema: zod.object({ a: zod.string() }),
        outputSchema: zod.object({ b: zod.string() })
      },
      view: {
        method: f2, // some function
        // ^!
        // Type '() => void' is not assignable to type '(() => void) & ((params: { c: string; }) => { d: string; })'.
        inputSchema: zod.object({ c: zod.string() }),
        outputSchema: zod.object({ d: zod.string() })
      }
    });
    ``