我正在使用TypeScript进行React项目。根据我在type definitions componentWillReceiveProps
'中看到的内容第一个参数应该是传递给Component类的相同泛型类型。我认为Component
已经实现ComponentLifecycle
,但我也尝试直接使用implements ComponentLifecycle
,而且我仍然没有达到我期望的类型安全性。
interface Props {
user: { login: string };
}
class Comp extends React.Component<Props> {
componentWillReceiveProps({ user }) {
// I think this should be two errors:
// `Property `ogin` does not exist on type
// Type `string` is not assignable to type 'void';
return user.ogin;
}
}
但是我没有得到任何错误,似乎传递到Props
的{{1}}只能在一个级别维护它们的类型。为了使其工作,我可以这样写:
componentWillReceiveProps
有没有办法让TypeScript正确键入已实现接口的泛型参数?这是类型定义中的错误吗?
答案 0 :(得分:1)
不,这不是错误。在类型中React.Component的定义是:
class Component<P, S> {
constructor(props?: P, context?: any);
setState<K extends keyof S>(
state: ((prevState: Readonly<S>, props: P) => (Pick<S, K> | S)) | (Pick<S, K> | S),
callback?: () => any
): void;
forceUpdate(callBack?: () => any): void;
render(): JSX.Element | null | false;
props: Readonly<{ children?: ReactNode }> & Readonly<P>;
state: Readonly<S>;
context: any;
refs: {
[key: string]: ReactInstance
};
}
生命周期方法及其类型没有任何内容。从typescript的角度来看,你只是用新方法扩展React.Component
,它试图从函数中的用户代码推断出参数的类型。当您明确添加类型时,Typescript会理解您的意图并帮助您。我现在只有一种方法可以精确地输入 - 将Component类定义为abstract,并将所有生命周期方法标记为abstract
。但是在这种情况下,你必须在子类定义中覆盖这些方法,但是你不想用React做大部分时间。如果您只是在常规类定义上定义生命周期方法,例如React.Component
,您仍然可以使用其他参数覆盖此定义,因此typescript不会强制您保持相同的函数形状并阻止您使用未知的参数。我认为只有通过向typescript添加sealed
函数属性才能修复它,这将禁止覆盖子代的函数类型。