我正在尝试创建一个行为与redux的connect
装饰器类似的装饰器:在装饰的组件中注入一些额外的props。我在输入文字时遇到问题
extra.d.ts
export interface ExtraProps {
extra: string;
}
// problem must be with this. Intent is to "add" the "extra" prop
// and not require it when the user actually renders it.
export function extra<P>(): (
Comp: ComponentType<P & ExtraProps>
) => ComponentType<P>;
sample.tsx
interface MyCompProps extends ExtraProps {
notSoExtra: string;
}
class MyComp extends React.Component<MyCompProps> {
render() {
console.log(this.props.extra, this.props.notSoExtra); // ok
return null;
}
}
// Decorating it here, prop types should be { notSoExtra: string }
const MyCompWithExtra = extra()(MyComp);
class App extends React.Component {
render() {
return <MyCompWithExtra notSoExtra="boring prop" />;
// error ^^^^^^
}
}
因此,在渲染MyCompWithExtra
时出现错误:
[ts]键入'{notSoExtra:string; }'与 输入'IntrinsicAttributes&{children ?: ReactNode; }'。
另外,当我像这样明确指定道具类型时:
const MyCompWithExtra = extra<MyCompProps>()(MyComp);
我在渲染时遇到了另一个错误
[ts]键入'{notSoExtra:string; }'无法分配给type 'IntrinsicAttributes&MyCompProps&{children ?: ReactNode; }'。
输入'{notSoExtra:string; }'无法分配给type “ MyCompProps”。 类型'{notSoExtra:string;类型中缺少属性'extra'。 }'。
如何键入装饰器,以便在渲染装饰组件时可以省略道具?
答案 0 :(得分:1)
第一个问题是,如果您在P
函数中指定extra
参数,而将在返回的函数调用中指定推断它所需的信息,则编译器将不会能够推断P
。
您可以使用单个函数,或者,如果要指定其他参数,则可以从其他函数返回通用函数。
但是,更大的问题是P & ExtraProps
并不意味着ExtraProps
中的属性将不包含在P
中。 P
将包含所有属性,其中& ExtraProps
会更多地限制这些属性的类型。
要创建从其他类型中排除属性的类型,可以使用Pick
组合来选择类型中的特定属性,并使用Exclude<keyof A, keyof B>
组合从列表中排除B
的键。 A
的键。
export interface ExtraProps {
extra: string;
}
export function extra<P extends ExtraProps>(
Comp: ComponentType<P>
) : ComponentType<Pick<P, Exclude<keyof P, keyof ExtraProps>>> {
return null as any;
}
//Usage
interface MyCompProps extends ExtraProps {
notSoExtra: string;
}
class MyComp extends React.Component<MyCompProps> {
render() {
console.log(this.props.extra, this.props.notSoExtra); // ok
return null;
}
}
const MyCompWithExtra = extra(MyComp);
let s = <MyCompWithExtra notSoExtra="boring prop" />;
注意:如果要允许用户选择指定extra
,则可以返回ComponentType<Pick<P, Exclude<keyof P, keyof ExtraProps>>> & Partial<ExtraProps>
。