【问题标题】:Get the static type from generic runtime type从通用运行时类型获取静态类型
【发布时间】:2023-02-23 02:26:33
【问题描述】:

尝试从 io-ts 创建的通用运行时类型中获取 ApiResponse<T> 静态 TS 通用类型。 official documentation没有信息

期望类型:

// runtime type
const ApiResponseCodec = <C extends t.Mixed>(codec: C) =>
  t.type({
    code: t.string,
    message: t.union([t.string, t.undefined]),
    result: codec,
  });

// expect type
type ApiResponse<T> = {
  code: string;
  message: string | undefined;
  result: T;
}

完整代码:

import { pipe } from 'fp-ts/lib/function';
import * as E from 'fp-ts/lib/Either';
import * as t from 'io-ts';

const ArticleDTOCodec = t.type({
  id: t.number,
  title: t.string,
});
type ArticleDTO = t.TypeOf<typeof ArticleDTOCodec>;

const PaginationResultCodec = <C extends t.Mixed>(codec: C) =>
  t.type({
    resultList: codec,
    totalItem: t.number,
  });

type PaginationResult<C extends t.Mixed> = t.TypeOf<ReturnType<typeof PaginationResultCodec<C>>>;

const ApiResponseCodec = <C extends t.Mixed>(codec: C) =>
  t.type({
    code: t.string,
    message: t.union([t.string, t.undefined]),
    result: codec,
  });

// Does not infer the type correctly.
type ApiResponse<C extends t.Mixed> = t.TypeOf<ReturnType<typeof ApiResponseCodec<C>>>;

const GetArticlesByPageResponseCodec = ApiResponseCodec(PaginationResultCodec(t.array(ArticleDTOCodec)));

export const decodeApiResponse = (res: ApiResponse<PaginationResult<ArticleDTO[]>>) => {
  return pipe(
    res,
    GetArticlesByPageResponseCodec.decode,
    E.fold(
      (e) => 'no',
      (res) => 'yes',
    ),
  );
};

ApiResponse&lt;PaginationResult&lt;ArticleDTO[]&gt;&gt; 抛出错误:

Type '{ resultList: unknown; totalItem: number; }' does not satisfy the constraint 'Mixed'.
  Type '{ resultList: unknown; totalItem: number; }' is missing the following properties from type 'Type<any, any, unknown>': name, is, validate, encode, and 7 more.ts(2344)

TS Playground

【问题讨论】:

    标签: typescript fp-ts


    【解决方案1】:

    您需要在ApiResponse&lt;PaginationResult&lt;ArticleDTO[]&gt;&gt; 中传递t.Type&lt;ArticleDTO[]&gt; 而不是ArticleDTO[],并将PaginationResult&lt;...&gt; 包装在t.Type 中。相反,您可以使用编解码器解码的实际类型作为类型变量。像这样的东西。

    import { pipe } from 'fp-ts/lib/function';
    import * as E from 'fp-ts/lib/Either';
    import * as t from 'io-ts';
    
    const ArticleDTOCodec = t.type({
      id: t.number,
      title: t.string,
    });
    type ArticleDTO = t.TypeOf<typeof ArticleDTOCodec>;
    
    const PaginationResultCodec = <A>(codec: t.Type<A>) =>
      t.type({
        resultList: codec,
        totalItem: t.number,
      });
    
    type PaginationResult<A> = t.TypeOf<ReturnType<typeof PaginationResultCodec<A>>>;
    
    const ApiResponseCodec = <A>(codec: t.Type<A>) =>
      t.type({
        code: t.string,
        message: t.union([t.string, t.undefined]),
        result: codec,
      });
    
    type ApiResponse<A> = t.TypeOf<ReturnType<typeof ApiResponseCodec<A>>>;
    
    const GetArticlesByPageResponseCodec = ApiResponseCodec(PaginationResultCodec(t.array(ArticleDTOCodec)));
    
    export const decodeApiResponse = (res: ApiResponse<PaginationResult<ArticleDTO[]>>) => {
      return pipe(
        res,
        GetArticlesByPageResponseCodec.decode,
        E.fold(
          (e) => 'no',
          (res) => 'yes',
        ),
      );
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 2013-01-10
      • 2011-03-05
      • 1970-01-01
      相关资源
      最近更新 更多