【问题标题】:TS infer from return type of callback property of an object parameterTS 从对象参数的回调属性的返回类型推断
【发布时间】:2021-11-08 23:11:42
【问题描述】:

我在尝试推断函数 post 返回类型的类型时遇到了这个问题。它的第二个参数是一个具有transform 属性的对象。因此,如果提供了transform 参数,那么post 的返回类型应该是transform 的返回类型,否则为post 函数提供的第一个泛型类型。希望能被理解。

type DefautlHttpCallInit = {  
  throttle?: number;
  baseUrl?: string;
  url?: string;
  onSend?(e: HttpCallInit) : void | Promise<void>;
}

export type HttpCallInit = RequestInit & DefautlHttpCallInit 

export type HttpCallInitOf<T> = RequestInit & DefautlHttpCallInit & {
  transform?: <TOut>(v: T) => TOut
};

export type HttpCallerInstance = {  
  post<T, TInit extends HttpCallInitOf<T>>(data?: T, init?: TInit): Promise<TInit extends {transform(e: T): infer XOut} ? XOut : T>;
  
}

//hack reference
let r = {} as HttpCallerInstance;

interface Post {
    id?: number;
    title: string;
}

interface User {
  id: number;
  userName: string;
}

interface UserPost extends Post{
  user: User
}

const user = {/* info props */} as User;

r.post({title: 'New post'} as Post, {
  //First: infer 
  transform(post) { 
    return Object.assign(post, {user}) as UserPost
  }
})
编译器选项
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "target": "Latest",
    "module": "ESNext",
    "moduleResolution": "node"
  }
}

Typescript Playground

我有这个错误日志:

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您将泛型 TOut 指定为转换本身的泛型,但这不是它所代表的,方法或函数上的泛型决定了它被调用时的行为。您想在声明时指定转换输出类型(与T 在同一位置),然后将其指定为post 函数like this 的泛型:

    export type HttpCallInitOf<T, TransformedType = T> = RequestInit & DefautlHttpCallInit & {
      transform?: (v: T) => TransformedType
    };
    
    export type HttpCallerInstance = {  
      post<T, TransformedType = T>(data?: T, init?: HttpCallInitOf<T,TransformedType>): Promise<TransformedType>;
      // TransformedType is defaults to T so if it can't be infered it stays as T
    }
    

    【讨论】:

    • 太棒了!谢谢!
    • 谁可以让transform 返回类型不依赖于T
    • 您是否遇到=T 无法正常工作而TransformedType 类似于`unknown` 的情况?代码示例会有所帮助
    • 没关系,我看到它工作正常,我只是做错了
    猜你喜欢
    • 1970-01-01
    • 2017-10-15
    • 2022-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 2019-12-06
    • 2016-07-23
    相关资源
    最近更新 更多