我想让我自己的输入元素表现得像 React 中的默认
<input />
一样,允许它受控(使用 value
)或不受控制(使用 defaultValue
)。
我在 TypeScript 中实现了这个,一切都很顺利,直到我向我的组件添加了另一个 prop。搞乱了
value
、defaultValue
和onChange
之间的关系。
这是我在添加额外道具之前的实现:
type OnChangeCallback = (newValue: string) => void;
interface Uncontrolled {
defaultValue?: string;
onChange?: OnChangeCallback;
}
interface Controlled {
value: string;
onChange: OnChangeCallback;
}
type Input = Uncontrolled | Controlled;
const input1: Input = {}; // OK
const input2: Input = {
defaultValue: "Hello, world!",
}; // OK
const input3: Input = {
onChange: newValue => console.log(`New value is ${newValue}`),
}; // OK
const input4: Input = {
value: "Hello, world!",
}; // Error: Missing onChange, all good
const input5: Input = {
value: "Hello, world!",
onChange: newValue => console.log(`New value is ${newValue}`),
}; // OK
然后我添加了一个名为
label
的道具,只是为了实验:
type Input = (Uncontrolled | Controlled) & {
label: string;
};
现在,TypeScript 允许使用带有
value
而不带 onChange
的组件:
const why: Input = {
label: "Oh dear",
value: "Hello, world!",
}; // Why is this OK now?
当我刚刚添加另一个属性时,
onChange
的要求去了哪里?value
通过引入
type Input = (Uncontrolled | Controlled) & {
label: string;
};
,
label
中可以有两个字符串值:Input
在这里您定义了满足标准的
const why: Input = {
label: "Oh dear",
value: "Hello, world!",
};
。