[英]TypeScript Conditionally Merge Prop Types Using Generics
Compiler tells me that properties propA
and propB
inside TestComponent
don't exist on type Props<T>
.编译器告诉我TestComponent
中的属性propA
和propB
在类型Props<T>
上不存在。 Is there something I'm missing or misunderstanding about conditional types?我对条件类型有什么遗漏或误解吗?
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
</>
My goal was to create an extendable and reusable type which properties can be controlled through generics.我的目标是创建一个可扩展和可重用的类型,其属性可以通过泛型进行控制。 I know this is also done with unions, but it's not quite easy to build other types on top of it.我知道这也是用联合完成的,但在它之上构建其他类型并不容易。
I think your first example of <TestComponent propA="propA" />
should also be invalid?我认为您的第一个<TestComponent propA="propA" />
示例也应该无效? After all, in that case, ìsA is of type
undefined`.毕竟,在那种情况下, ìsA is of type
undefined 。
I changed your Props<T>
into this Props
instead:我把你的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
}
}
Your usage of it is also validated properly now:您对它的使用现在也得到了正确验证:
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
Interestingly, if I use prop.isA === true
, TypeScript behaves better:有趣的是,如果我使用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
}
}
That should be good enough in your case I hope?我希望在你的情况下应该足够好? Although I'm surprised in the difference between if (props.isA)
and if (props.isA === true)
.虽然我对if (props.isA)
和if (props.isA === true)
之间的区别感到惊讶。 Mind that this requires TypeScript to run in strict mode, with noImplicitAny
enabled to be specific.请注意,这需要 TypeScript 在严格模式下运行,并启用noImplicitAny
以使其特定。 Otherwise you need to use if (props.isA === true)
.否则你需要使用if (props.isA === true)
。 Weird, but running with noImplicitAny
disabled is very rare anyway.很奇怪,但是在noImplicitAny
禁用的情况下运行是非常罕见的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.