【发布时间】:2021-11-20 06:14:27
【问题描述】:
我想知道在 TypeScript 中是否有可能根据父项的 prop 推断类型。
让我用一个例子更好地解释一下:假设我有<Parent> 和<Child> 组件,以及一个接口IMyComplexObject。
interface IMyComplexObject {
name: string;
surname: string;
}
const MyApp = (props) => {
const [obj, setObj] = React.useState<IMyComplexObject>({name: 'Foo', surname: 'Bar'});
return (
<Parent context={obj}>
<Child value={'name'} />
</Parent>
);
}
所以,我要问的是:当我写<Child value={'name'} /> 时,是否可以推断出value 属性的接受值是'name' | 'surname',这是obj 的键?
我知道,如果我只有一个组件,事情会很容易。假设:
interface IChildProps<T> {
ctx: T;
value: keyof T;
}
- - -
return <Child ctx={obj} value={'name'} />
然后,智能感知器会告诉我哪些是可接受的值:
但是,当定义上下文的是 <Parent> 组件而不是组件本身时,事情会变得更加棘手。
编辑:
为了回答@captain-yossarian 的提议,<Child> 上的泛型类型的问题是我最终会得到如下代码:
<Parent context={obj}>
<Child<IMyComplexObject> value={...} />
<Child<IMyComplexObject> value={...} />
<Child<IMyComplexObject> value={...} />
...
</Parent>
泛型太多(每个孩子一个)。更重要的是,传递给<Parent> 的obj 的类型与传递给<Child>s 组件的泛型类型之间没有实际联系。
因此,例如,这样的事情仍然是“合法的”:
interface IObj_1 {
age: number;
}
interface IObj_2 {
name: string;
}
const [obj1, setObj1] = React.useState<IObj_1>({age: 7});
const [obj2, setObj2] = React.useState<IObj_2>({name: 'Foo'});
return (
<Parent context={obj1}>
<Child<IObj_2> value={'name'} />
</Parent>
);
【问题讨论】:
-
我不确定这种方法在 React 中是否真的有意义,理论上组件应该尽可能自包含,为什么要这样做? (只是想知道这是否是一个 XY 问题)
-
理想情况下,制作一组要一起使用的组件。我简化了这个例子,但我想,如果我使用组件的真实名称,事情会更容易理解。假设父级称为
<MyForm>,子级称为<MyTextInput>:目标是在<MyForm>中定义一个上下文,并且每个子级都可以利用该上下文。
标签: reactjs typescript