当直接在组件上或在另一个道具内指定道具时,为什么键入不同



这可能看起来很令人困惑,但请考虑下一个组件(参见游乐场(:


type Props<T> = {
initValue: T,
process: (value: T) => T
}
export const Input = <T,>({
initValue,
process,
}: Props<T>): React.ReactElement => {
const [value, setValue] = useState<T>(initValue);
return (
<input
value={value as unknown as string}
onChange={({ target: { value: dirtyValue } }) => {
const processedValue = process(dirtyValue as unknown as T);
setValue(processedValue);
}}
/>
);
};
() => (
// fails because value is number, and indexOf doesn't exist on number
<Input initValue={4} process={value => `${value.indexOf('4')}`} />
);
() => (
// fails because the return type of process is number, not string
<Input initValue={'4'} process={value => value.indexOf('4')} />
);
() => (
// passes because value is string, indexOf exists on string, and process returns string
<Input initValue={'4'} process={value => `${value.indexOf('4')}`} />
);

忽略组件主体本身,重点是键入。这种类型化的目的是使组件在参数类型和期望的返回类型中继承process内部的initValue的类型。

现在检查我是否复制了与上一个完全相同的道具(通过(,但正在传播:

() => (
// fails because value is type unknown (not sure why)
<Input {...{initValue: '4', process: value => `${value.indexOf('4')}`}} />
);

现在它说value是类型unknown。为什么?

这可能是类型推理系统的缺陷。这不是道具本身的问题,因为如果你写

Input({...{initValue: '4', process: value => `${value.indexOf('4')}`}})

也有同样的错误,没有涉及JSX或react(这段代码没有多大意义,但从typescript的角度来看,这是一个有效的函数调用(。

不确定为什么这不起作用,但有很多解决办法:

<Input<string> {...{initValue: '4', process: value => `${value.indexOf('4')}`}} />
// The prettiest imho
<Input {...{initValue: '4', process: (value: string) => `${value.indexOf('4')}`}} />
<Input {...{initValue: '4', process: value => `${value.indexOf('4')}`} as Props<string>} />

无论如何,在实践中,不确定为什么要在没有事先将此对象分配给类型化变量的情况下编写这样的排列。除非你只是对为什么会发生这种情况感兴趣,在这种情况下,我也想知道一个更准确的答案:p

最新更新