英文:
Infer prop type based on value being presnt
问题
这个示例的主要目标是在实体属性存在时,使 onClick 回调函数接收实体字符串,如果不存在实体属性,则不接收任何参数。
type SnakeOrCamelDomains = "light" | "switch" | "input_boolean" | "fan";
interface TestProps<S extends `${SnakeOrCamelDomains}.${string}`> {
entity?: S;
onClick: S extends `${SnakeOrCamelDomains}.${string}` ? (entity: string) => void : () => void;
}
function Test<S extends `${SnakeOrCamelDomains}.${string}`>({
entity,
onClick,
}: TestProps<S>) {
return <button onClick={() => {
if (typeof entity === 'string') {
onClick(entity);
} else {
onClick();
}
}}>{entity}</button>;
}
这个示例在 TypeScript 中无法正常工作,因为 TypeScript 在此时无法了解 entity 或其值,因此期望你传递一个参数给 onClick。这种情况是否可能在 TypeScript 中实现呢?
英文:
I have a very simple example of what i'm trying to achieve, basically when the entity prop is present, i want the onClick callback to receive the entity string, if not it would receive nothing
type SnakeOrCamelDomains = "light" | "switch" | "input_boolean" | "fan";
interface TestProps<S extends `${SnakeOrCamelDomains}.${string}`> {
entity?: S;
onClick: S extends `${SnakeOrCamelDomains}.${string}` ? (entity: string) => void : () => void;
}
function Test<S extends `${SnakeOrCamelDomains}.${string}`>({
entity,
onClick,
}: TestProps<S>) {
return <button onClick={() => {
if (typeof entity === 'string') {
onClick(entity);
} else {
onClick();
}
}}>{entity}</button>
}
This example above doesn't work with typescript, it's expecting me to pass an argument to onClick, naturually... as typescript doesn't know anything about entity or it's value at this point.
Is this possible with typescript?
答案1
得分: 1
错误的原因是类型 S
是 ${SnakeOrCamelDomains}.${string}
的子类型,因此 TypeScript 期望 S
始终是一个字符串。
即使 entity
是可选的并且可能为undefined,由于 S
始终扩展${SnakeOrCamelDomains}.${string}
,TypeScript 仍然推断 onClick
的类型为 (entity: string) => void
。
如果您希望 onClick
函数可以选择地接受一个实体作为参数,您可以将其类型更改为接受一个可选的字符串参数的函数:
interface TestProps<S extends `${SnakeOrCamelDomains}.${string}`> {
entity?: S;
onClick: (entity?: string) => void;
}
英文:
The reason you're having this error is because the type S
is a subtype of ${SnakeOrCamelDomains}.${string}
, and because of that, TypeScript expects S
to always be a string.
Even though entity
is optional and could be undefined, TypeScript still infers onClick
as (entity: string) => void
due to S
always extending ${SnakeOrCamelDomains}.${string}
.
If you want the onClick
function to be optionally called with an entity, you can change its type to a function that takes an optional string argument:
interface TestProps<S extends `${SnakeOrCamelDomains}.${string}`> {
entity?: S;
onClick: (entity?: string) => void;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论