首页 > 解决方案 > 基于函数参数的条件类型检查

问题描述

我正在编写一个自定义 Hook,它可以采用一个或两个字符串,或者一个具有更细粒度参数的对象。我想添加一个条件类型检查来检查该参数的类型并基于它做一些逻辑。以下是相关的片段:

// The hook itself
const [error, loading, data] = useFirestore('posts', 'test'); // in a string version
const [error, loading, data] = useFirestore({...someProps}); // in a object version version
// The types that i defined for them
type queryType<T> = T extends string ? string : documentQueryType;
type docType<T> = T extends string ? string : never;

type documentQueryType = {
    collection: string;
    query: string[] | string[][];
    limit: number;
    orderBy: string; // todo limit this to be only special words
    order: string; // todo same as above
    startAt: number;
    endAt: number;
};
// The function that is in the question
export const useFirestore = <T>(query: queryType<T>, doc?: docType<T>) => {...rest of the function

我将如何使最后一个片段工作,以便在传递一个对象时它设置doc为从不,而当传递一个字符串时将其设置doc为字符串?

标签: reactjstypescriptfirebase

解决方案


这可以通过条件类型部分实现,但它可能不是 100% 类型安全的。由于是可选的,因此当是 adoc时不需要它,并且仍然允许当是对象时。querystringundefinedquery

但是,如果这两种情况都不是问题,则可以使用条件类型来实现:

// Simplified type
type DocumentQueryType = {
  collection: string;
};

// The two types of queries that are accepted
type QueryTypes = string | DocumentQueryType;

// Given the query type, infer the doc type
type InferDocType<QueryType> = QueryType extends string ? string : never;

const useFirestore = <QueryType extends QueryTypes>(query: QueryType, doc?: InferDocType<QueryType>) => { }

// Valid Examples
useFirestore('posts', 'test');
useFirestore({ collection: "" });

// Valid Examples (may not want these?)
useFirestore('posts');
useFirestore({ collection: "" }, undefined);

// Invalid Examples
useFirestore({ collection: "" }, "test");
// Argument of type '"test"' is not assignable to parameter of type 'undefined'.(2345)
useFirestore('posts', null);
// Argument of type 'null' is not assignable to parameter of type 'string | undefined'.(2345)

推荐阅读