typescript 基于输入参数的条件返回类型

yqlxgs2m  于 2023-02-05  发布在  TypeScript
关注(0)|答案(3)|浏览(147)

描述

我希望根据输入参数返回stringstring[],在本例中,输入参数名为options,它是input属性:options.input.
我试图让TypeScript根据此输入推断它,但似乎无法使它工作。

类型

类型定义如下。

const TextInputTypes = <const>[
    "text",
    "number",
    "password",
    "email",
    "tel",
    "url",
    "search",
    "color",
    "date",
    "time",
    "datetime-local",
    "month",
    "week",
    "range",
    "file",
];
const CheckboxTypes = <const>["checkbox", "radio"];
const SelectTypes = <const>["select"];

type TextType = (typeof TextInputTypes)[number];
type CheckType = (typeof CheckboxTypes)[number] | (typeof SelectTypes)[number];
type InputType = TextType | CheckType;

type PromptOptions = {
    input: InputType;
    placeholder: string;
    entries: { value: string; text: string }[];
};

示例

如果options.input为TextType,则返回string,否则返回string[]
编号
我试过了,但没有成功

type ReturnType<T extends InputType> = T extends TextType ? string : string[];

const value: ReturnType<typeof options.input>;

它基本上在一个函数中,如下所示:

function foo = (name: string, options: Options) => {}

输出仅显示string | string[]

lmvvr0a8

lmvvr0a81#

除了@JDB和@adsy提供的答案之外,您还可以使用extends来实现您的目标:

type StringOrArrayString<T extends PromptOptions> = T extends {input: TextType} ? string : string[];

function foo<T extends PromptOptions>(name: string, options: T): StringOrArrayString<T> {
  // ...
}

检查这个Playground

qco9c6ql

qco9c6ql2#

使用函数重载。

const TextInputTypes = [
    "text",
    "number",
    "password",
    "email",
    "tel",
    "url",
    "search",
    "color",
    "date",
    "time",
    "datetime-local",
    "month",
    "week",
    "range",
    "file",
] as const;
const CheckboxTypes = ["checkbox", "radio"];
const SelectTypes = ["select"] as const;
type TextType = (typeof TextInputTypes)[number];
type CheckType = (typeof CheckboxTypes)[number] | (typeof SelectTypes)[number];
type InputType = TextType | CheckType;

type PromptOptions<T extends InputType> = {
    input: T;
    placeholder: string;
    entries: { value: string; text: string }[];
};

const isCheckboxType = (typeString: string): typeString is CheckType => (CheckboxTypes as string[]).includes(typeString)

function foo (name: string, options: PromptOptions<TextType>): string
function foo (name: string, options: PromptOptions<CheckType>): string[]
function foo (name: string, options: PromptOptions<TextType | CheckType>): string | string[]  {
  if (CheckboxTypes.includes(options.input as CheckType)) {
    // TODO
    return ''
  }

  // transformToDocument
  return []
}

const arrayExample = foo('test', {input: 'select', placeholder: 'test', entries: []})
const stringExample = foo('test', {input: 'text', placeholder: 'test', entries: []})


使用函数重载。

nue99wik

nue99wik3#

可以使用函数重载检测input属性的类型,然后返回stringstring[]。请注意,这需要将匿名函数(const foo = () => {})更改为命名函数(function foo() {})。

function isTextType(inputType:string):inputType is typeof TextInputTypes[number] {
    return (TextInputTypes as readonly string[]).includes(inputType);
}

type PromptOptions = {
    placeholder: string;
    entries: { value: string; text: string }[];
}
type TextTypePromptOptions = PromptOptions & {
    input: TextType;
};
type CheckTypePromptOptions = PromptOptions & {
    input: CheckType;
}

function foo(name:string, options:TextTypePromptOptions):string;
function foo(name:string, options:CheckTypePromptOptions):string[];
function foo(name:string, options:TextTypePromptOptions|CheckTypePromptOptions):string|string[] {
    if (isTextType(options.input)) {
        return "";
    } else {
        return [];
    }
}

// const result1: string
const result1 = foo("", { placeholder: "", entries: [], input: "text" });
// const result2: string[]
const result2 = foo("", { placeholder: "", entries: [], input: "radio" });

对于像您这样的简单情况,这很容易阅读和理解,但是如果您有许多这样的参数,那么写出所有可能的重载可能会有点乏味。

相关问题