typescript - TypeScript 使用泛型有条件地合并道具类型
问题描述
编译器告诉我type 上不存在propertiespropA
和propB
inside 。我对条件类型有什么遗漏或误解吗?TestComponent
Props<T>
import React from 'react';
type PropsBase<T extends boolean | undefined> = {
isA?: T;
};
type PropsA = {
propA: string;
};
type PropsB = {
propB: string;
};
type Props<T extends boolean | undefined> = PropsBase<T> & (T extends false | undefined ? PropsB : PropsA);
function TestComponent<T extends boolean | undefined = true>(props: Props<T>) {
if (props.isA) {
return <>{props.propA}</>; // Property 'propA' does not exist
}
if (!props.isA) {
return <>{props.propB}</>; // Property 'propB' does not exist
}
return <></>;
}
<>
<TestComponent propA="propA" /> // Should be valid
<TestComponent isA propA="propA" /> // Should be valid
<TestComponent isA={false} propB="propB" /> // Should be valid
<TestComponent isA propB="propB" /> // Should be invalid
</>
我的目标是创建一个可扩展和可重用的类型,其属性可以通过泛型来控制。我知道这也可以通过联合来完成,但是在它之上构建其他类型并不容易。
解决方案
我认为您的第一个示例<TestComponent propA="propA" />
也应该无效?毕竟,在那种情况下,ìsA is of type
undefined`。
我把你Props<T>
改成了这个Props
:
type Props = ({ isA: true } & PropsA) | ({ isA?: false } & PropsB);
function TestComponent(props: Props) {
if (props.isA) {
return props.propA; // OK
}
if (!props.isA) {
return props.propB; // OK
}
}
您对它的使用现在也得到了正确验证:
TestComponent({ propA: 'propA' }); // Property 'isA' is missing
TestComponent({ propB: 'propB' }); // OK
TestComponent({ isA: true, propA: 'propA' }); // OK
TestComponent({ isA: false, propB: 'propB' }); // OK
TestComponent({ isA: true, propB: 'propB' }); // 'propB' does not exist
有趣的是,如果我使用prop.isA === true
,TypeScript 的表现会更好:
function TestComponent(props: Props) {
if (props.isA === true) {
return props.propA; // OK
}
const isA = props.isA; // type `false | undefined`
if (!props.isA) {
return props.propB; // OK
}
}
我希望在你的情况下这应该足够好了吗?尽管我对 和 之间的区别感到if (props.isA)
惊讶if (props.isA === true)
。请注意,这需要 TypeScript 在严格模式下运行,并且noImplicitAny
启用是特定的。否则你需要使用if (props.isA === true)
. 很奇怪,但noImplicitAny
无论如何,在禁用的情况下运行是非常罕见的。
推荐阅读
- docker - 文件挂载为目录而不是 docker-in-docker (dind) 中的文件
- sql - 多列上的 CASE 表达式
- php - 将组数据填充到 Highcharts 上的特定系列
- python - 以全屏模式显示单个图像(如 powerpoint)
- flutter - 在 Dart 中导入整个文件和只导入带有 show 的类有什么区别?
- javascript - 如何使用 Directus Javascript SDK 进行条件过滤?
- android - 查找用户是否在锁定屏幕上禁用通知
- python - 如何将更新的DataFrame实时输入sql或db
- .net - 同时调用 Multi-WebApi 导致在前一个操作完成之前在此上下文上启动了第二个操作
- c++ - 标题中的模板规范问题