[英]How to correctly type an object with alternate keys in TypeScript?
我想创建一个 TypeScript 类型,它涉及一组固定键,以及一组备用键组,例如:
type Props = {
id: string
} & (
{
height: number,
width: number
}
| {color: string}
)
现在,在这种情况下,它正确地强制每个组都具有该组的所有属性,或者没有,即:我不能在不使用width
的情况下使用height
。
现在,如果我还想允许没有任何可选键的替代方案,我知道实际提供所需结果的唯一选项是使用{}
作为替代方案。
但是 lint 规则@typescript-eslint/ban-types
不允许这样做,说根据用例我应该Record<string, unknown>
, unknown
或Record<string, never>
。
但这些都不适用于这种情况。 如果我使用unknown
或Record<string, never>
或object
TS 不允许替代项中的任何键。 如果我使用Record<string, unknown>
它不允许任何密钥,除非我填写其中一个备用密钥组。
有没有我遗漏的另一种方法,或者我应该忽略 lint 规则来实现这个?
我发现在 React 中重载是一个更好的例子。
您可以为每个要支持的模式创建一个重载。
import React from 'react'
type RequiredProps = { id: string }
type SizeProps = { height: number, width: number }
type ColorProps = { color: string }
type AllOptionProps = SizeProps | ColorProps
function MyComponent(props: RequiredProps): JSX.Element
function MyComponent(props: RequiredProps & SizeProps): JSX.Element
function MyComponent(props: RequiredProps & ColorProps): JSX.Element
function MyComponent(props: RequiredProps & Partial<AllOptionProps>) {
console.log(props.id)
if ('width' in props) console.log(props.width)
if ('color' in props) console.log(props.color)
return <></>
}
const a = <MyComponent id='abc' />
const b = <MyComponent id='abc' width={50} height={100} />
const c = <MyComponent id='abc' color='red' />
const d = <MyComponent id='abc' width={50} /> // error
第二种方法是创建一个联合,其中所有 props 都在所有成员中,但如果你说你可以拥有它们,则强制为undefined
。
import React from 'react'
type RequiredProps = { id: string }
type NoOptionsProps = {
height?: undefined,
width?: undefined,
color?: undefined
}
type SizeProps = {
height: number,
width: number,
color?: undefined
}
type ColorProps = {
height?: undefined,
width?: undefined,
color: string
}
type Props = RequiredProps & (NoOptionsProps | SizeProps | ColorProps)
function MyComponent(props: Props) {
console.log(props.id)
console.log(props.width)
console.log(props.color)
return <></>
}
const a = <MyComponent id='abc' />
const b = <MyComponent id='abc' width={50} height={100} />
const c = <MyComponent id='abc' color='red' />
const d = <MyComponent id='abc' width={50} /> // error
您可以尝试FC
的交集:
import React, { FC } from 'react'
interface Base {
id: string
}
interface WithRect extends Base {
height: number,
width: number
}
interface WithColor extends Base {
color: string
}
type Result = FC<WithColor> & FC<WithRect> & FC<Base>
const App: Result = (props) => <p></p>
const jsx = <App id="hello" color="green" /> // ok
const jsx____ = <App id="hello" /> // ok
const jsx___ = <App id="hello" width={1} height={1} /> // ok
const jsx_ = <App id="hello" color="green" height={1} /> // expected error
const jsx__ = <App id="hello" height={1} /> // expected error
这种行为类似于 function 重载,我什至可以说 95% 相似但不相等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.