簡體   English   中英

如何在 TypeScript 中使用備用鍵正確鍵入 object?

[英]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>unknownRecord<string, never>

但這些都不適用於這種情況。 如果我使用unknownRecord<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% 相似但不相等。

如果你對輸入 React component props 感興趣,請參閱我的文章my blogdev.to

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM