打字稿:如何定义条件打字稿道具以访问 React 中的对象?
Typescript: How to define conditional typescript props to access object in React?
我正在尝试使用 React props 作为访问对象的键。根据道具 type
是“solid”还是“outline”,将决定我使用什么数据。嵌套的“solid”和“outline”对象中的对象键不相同,因此 Typescript 抱怨说它可能无法访问该键。你如何让 typescript 快乐?
代码可以正常运行,但不确定如何消除错误。
const icons = {
outline: {
default: "x1",
icon1: "icon1"
},
solid: {
default: "x2",
icon2: "icon2"
}
} as const;
// If type is solid, you can only choose a solid iconName
// If type is outline, you can only choose an outlined iconName
type ConditionalProps =
| { type: "solid"; iconName: keyof typeof icons.solid }
| { type: "outline"; iconName: keyof typeof icons.outline };
const App = ({type = "outline", iconName = "default"}: ConditionalProps) => {
// Typescript doesn't complain here
const text1 = icons[type];
// TSERROR: Typescript complains here
const text2 = icons[type][iconName];
return (
<div>
<h1>The chosen icon is...</h1>
<h2>{Object.keys(text1)}</h2>
<h2>{text2}</h2>
</div>
);
}
export default App;
打字稿错误是:
// TSERROR
Element implicitly has an 'any' type because expression of type
'"icon2" | "icon1" | "default"' can't be used to index type
'{ readonly default: "defaultOutline"; readonly icon2: "icon2"; }
| { readonly default: "defaultSolid"; readonly icon1: "icon1"; }'.
Property 'icon2' does not exist on type
'{ readonly default: "defaultOutline"; readonly icon2: "icon2"; }
| { readonly default: "defaultSolid"; readonly icon1: "icon1"; }'.ts(7053)
简答:你不能。至少,安全。嗯,有点。
如果你想有一些类型安全,你首先需要缩小每个案例的联合,像这样:
function matchIcon(props: ConditionalProps) {
if (props.type === "outline") {
return icons[props.type][props.iconName];
}
if (props.type === "solid") {
return icons[props.type][props.iconName];
}
}
这有点多余,但很安全。
另一种方法是抑制错误,但会降低代码的安全性:
const text2 =
icons[props.type][
props.iconName as keyof typeof icons.solid & keyof typeof icons.outline
];
因为icons[props.type]
可以是icons.outline和icons.solid,我们需要传递一个同时满足这两种情况的iconName
值。 keyof typeof icons.solid & keyof typeof icons.outline
只是可能值的一个子集,如果为 outline
或 solid
提供,它仍然有效。我们主要是在欺骗编译器。
我正在尝试使用 React props 作为访问对象的键。根据道具 type
是“solid”还是“outline”,将决定我使用什么数据。嵌套的“solid”和“outline”对象中的对象键不相同,因此 Typescript 抱怨说它可能无法访问该键。你如何让 typescript 快乐?
代码可以正常运行,但不确定如何消除错误。
const icons = {
outline: {
default: "x1",
icon1: "icon1"
},
solid: {
default: "x2",
icon2: "icon2"
}
} as const;
// If type is solid, you can only choose a solid iconName
// If type is outline, you can only choose an outlined iconName
type ConditionalProps =
| { type: "solid"; iconName: keyof typeof icons.solid }
| { type: "outline"; iconName: keyof typeof icons.outline };
const App = ({type = "outline", iconName = "default"}: ConditionalProps) => {
// Typescript doesn't complain here
const text1 = icons[type];
// TSERROR: Typescript complains here
const text2 = icons[type][iconName];
return (
<div>
<h1>The chosen icon is...</h1>
<h2>{Object.keys(text1)}</h2>
<h2>{text2}</h2>
</div>
);
}
export default App;
打字稿错误是:
// TSERROR
Element implicitly has an 'any' type because expression of type
'"icon2" | "icon1" | "default"' can't be used to index type
'{ readonly default: "defaultOutline"; readonly icon2: "icon2"; }
| { readonly default: "defaultSolid"; readonly icon1: "icon1"; }'.
Property 'icon2' does not exist on type
'{ readonly default: "defaultOutline"; readonly icon2: "icon2"; }
| { readonly default: "defaultSolid"; readonly icon1: "icon1"; }'.ts(7053)
简答:你不能。至少,安全。嗯,有点。
如果你想有一些类型安全,你首先需要缩小每个案例的联合,像这样:
function matchIcon(props: ConditionalProps) {
if (props.type === "outline") {
return icons[props.type][props.iconName];
}
if (props.type === "solid") {
return icons[props.type][props.iconName];
}
}
这有点多余,但很安全。
另一种方法是抑制错误,但会降低代码的安全性:
const text2 =
icons[props.type][
props.iconName as keyof typeof icons.solid & keyof typeof icons.outline
];
因为icons[props.type]
可以是icons.outline和icons.solid,我们需要传递一个同时满足这两种情况的iconName
值。 keyof typeof icons.solid & keyof typeof icons.outline
只是可能值的一个子集,如果为 outline
或 solid
提供,它仍然有效。我们主要是在欺骗编译器。