[英]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.