选择元素上的 TypeScript 值约束

问题描述 投票:0回答:1

我现在为此苦苦挣扎了一段时间。

我想创建一个 React 选择组件,其中 TS 可以从一组选项值中推断组件的值类型。

比方说:

const myFakeValueSet = [
  "dc9d15ee-7794-470e-9dcf-a8d1dd1a6fcf",
  "1bda4f79-a199-40ce-985b-fa217809d568",
  "e91b2cac-48f6-4d60-b86f-ece02f076837",
  "66a9d7ac-9b25-4e52-9de3-4b7238135b39"
] as const;

const optionsWithTypedValues: Option<typeof myFakeValueSet[number]>[] = myFakeValueSet.map((fakeValue) => ({
  value: fakeValue,
  label: fakeValue
}));


const MyComponent = <Select 
  options={optionsWithTypedValues} 
  value={"something"} // should throw TS error
/>;

这是一个有效的实现:

type OptionValue = typeof myFakeValueSet[number];
type Option<Type extends OptionValue> = {
  value: Type;
  label: string;
};
type SelectProps<Type extends OptionValue> = {
  options: Option<Type>[];
  value: Type;
  onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void;
};

function Select<Type extends OptionValue>({ options, value, onChange }: SelectProps<Type>) {

  return (
    <select value={value} onChange={onChange}>
      {options.map((option) => (
        <option key={option.value} value={option.value}>
          {option.label}
        </option>
      ))}
    </select>
  );
}

但是如您所见,我必须从非泛型的

T
扩展泛型
OptionValue
。所以我尝试从选择默认值
string | number | readonly string[] | undefined
进行扩展,但是如果我这样做,当我为我的组件提供意外值(例如
"something"
)时,它不会抛出错误,并且会更改类型到原来的T联合+
"something"
。这就像 TS 从选项的值和
value
(实际上是
defaultValue
)推断类型。

我试图让它完全通用,所以 TS 会知道我只能从我给他的选项集中为 Select 组件设置一个值。

有可能吗?

原始示例:https://codesandbox.io/s/react-typescript-forked-g34stp

reactjs typescript dom
1个回答
0
投票

你只需要做一点小改动,它就会按照你想要的方式工作。基本上,您需要告诉 TS,这些值只能是

myFakeValueSet
中的值。对不对,
typeof myFakeValueSet
string[]
。您需要告诉 TS 将其视为不可变数组。你可以用
const myFakeValueSet = [...] as const
来做到这一点。这样会导致TS在你通过的时候报错
value={"something"}

© www.soinside.com 2019 - 2024. All rights reserved.