【问题标题】:How to get a literal type from a class property (after passing the class as argument) for a computed property name?如何从类属性(将类作为参数传递后)获取计算属性名称的文字类型?
【发布时间】:2021-07-10 10:02:12
【问题描述】:

刚才我问了this question,现在我有一个跟进的:)

请考虑以下代码:

import { ClassConstructor } from "class-transformer";
import { useQuery as useApolloQuery } from "@apollo/client";

class Book {
  readonly many = "books" as const;
  bookData: any;
}

export const useQueryWrapper = <T>(cls: ClassConstructor<T>, queryString) => {
  return useApolloQuery<{ [cls.prototype.many]: T[] }>(queryString);
};

const { data } = useQueryWrapper(Book, "..."); // Book or any other class with a literal `many` prop

TS 将数据识别为以下类型:

const data: {} | undefined

我想让 TS 知道 data 有一个属性 books

const data: {
    books: Book[];
} | undefined

有可能吗?

【问题讨论】:

    标签: typescript typescript-typings apollo-client typescript-generics class-transformer


    【解决方案1】:

    这可以通过 index access types 和 mapped types (playground) 的组合来实现:

    class Book {
      readonly many = "books" as const;
      bookData: any;
    }
    
    class Page {
      readonly many = "pages" as const;
      bookData: any;
    }
    
    type ManyType = { readonly many: string };
    
    type QueryResult<T extends ManyType> = {
      // using K in T["many"] to create an object with a key of value T["many"], e.g. "books", "pages", etc.
      [K in T["many"]]: T[]; 
    };
    
    type ClassConstructor<T> = new (...args: any[]) => T;
    
    function useQueryWrapper<T extends ManyType>(
      cls: ClassConstructor<T>,
      queryString: string
    ): QueryResult<T> | undefined {
      return {} as any;
    }
    
    const books = useQueryWrapper(Book, "...")?.books; // Book[] | undefined
    const pages = useQueryWrapper(Page, "...")?.pages; // Page[] | undefined
    

    【讨论】:

    • 看起来很有希望。给我一点时间。我正在仔细检查一切:)
    猜你喜欢
    • 1970-01-01
    • 2021-07-10
    • 2021-11-30
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 2011-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多