我想让Typescript 抱怨丢失的props ,基于一个根本没有通过的props .

请考虑以下示例:

type MyComponentProps = { isOpen: boolean } & (
    | ({ withButton?: true | undefined | void | never } & { buttonText: string })
    | ({ withButton?: false } & { buttonText?: never })
)

const MyComponent: React.FC<MyComponentProps> = ({ withButton = true, buttonText }) => {
    return <></>
}

const AnotherComponent = () => {
    // TypeScript does not complain, but I wanted it to require `buttonText` when `withButton` is not passed
    return <MyComponent isOpen={false} />
}

有没有什么方法可以改变条件MyComponentProps,这样当我根本没有通过withButton时,它就需要buttonText了?

推荐答案

你可以在withButton属性的值为false时将其设置为必填,这样它就不会与缺少它的情况匹配:

type MyComponentProps = { isOpen: boolean } & (
    | ({ withButton?: true | undefined | never } & { buttonText: string }) // If withButton prop is true or missing, buttonText prop is required
    | ({ withButton: false } & { buttonText?: never }) // If withButton prop is false, buttonText prop is forbidden (or at most undefined)
)

现在,当缺少withButtonprops 时,TypeScrip会正确地发出警告,但同时也会缺少buttonTextprops (即现在需要):

const AnotherComponent = () => {
    return (<>
        <MyComponent isOpen={false} />
        {/*~~~~~~~~~ Property 'withButton' is missing in type '{ isOpen: false; }' but required in type '{ withButton: false; }'.(2322)  */}
        <MyComponent withButton={true} isOpen={false} />
        {/*~~~~~~~~~ Property 'buttonText' is missing in type '{ withButton: true; isOpen: false; }' but required in type '{ buttonText: string; }'.(2322) */}
        <MyComponent withButton={false} buttonText="should not be there" isOpen={false} />
        {/*~~~~~~~~~ Type 'string' is not assignable to type 'undefined'.(2322) */}
        <MyComponent withButton={false} isOpen={false} />{/* Okay */}
        <MyComponent withButton={false} buttonText={undefined} isOpen={false} />{/* Okay */}
        <MyComponent withButton={true} buttonText="okay" isOpen={false} />{/* Okay */}
        <MyComponent withButton={undefined} buttonText="okay as well" isOpen={false} />{/* Okay */}
    </>)
}

Playground Link


<MyComponent isOpen={false} />表示期望withButton,但我希望它期望buttonText

如果您的意思是希望TS错误提示大约buttonText而不是withButton,那么只需确保将您希望TS默认用于提示的类型放在联合的最后:

type MyComponentProps = { isOpen: boolean } & (
    | ({ withButton: false } & { buttonText?: never }) // If withButton prop is false, buttonText prop is forbidden (or at most undefined)
    // Put last in union the type that you want to hint to by default
    | ({ withButton?: true | undefined | never } & { buttonText: string }) // If withButton prop is true or missing, buttonText prop is required
)

const AnotherComponent = () => {
    return (<>
        <MyComponent isOpen={false} />
        {/*~~~~~~~~~ Property 'buttonText' is missing in type '{ isOpen: false; }' but required in type '{ buttonText: string; }'.(2322)  */}
        <MyComponent buttonText="okay as well again" isOpen={false} />{/* Okay */}
    </>)
}

Playground Link

Typescript相关问答推荐

类型安全JSON解析

如何在TypeScript对象迭代中根据键推断值类型?

有没有一种方法可以在保持类型的可选状态的同时更改类型?

返回同时具有固定键和变量键的对象的函数的返回类型

泛型函数即使没有提供类型

如何使函数接受类型脚本中具有正确类型的链接修饰符数组

如何在编译时为不带常量的参数引发错误

了解类型规则中的关键字

在分配给类型的只读变量中维护const的类型

如何消除在Next.js中使用Reaction上下文的延迟?

Typescript 类型守卫一个类泛型?

自动通用回调

S,为什么我的T扩展未定义的条件在属性的上下文中不起作用?

从类型脚本中元组的尾部获取第n个类型

错误:NG02200:找不到类型为';对象';的其他支持对象';[对象对象]';.例如数组

埃斯林特警告危险使用&as";

T的typeof键的Typescript定义

如何在Vuetify 3中导入TypeScript类型?

有没有办法将类型与关键更改相匹配?

创建通过删除参数来转换函数的对象文字的类型