[英]React-Typescript: How do I type a default prop?
Let's say I have this component class: 假设我有这个组件类:
interface SomeComponentProps {
someOptionalProperty?: string;
}
interface SomeComponentState { /* ... */ }
class SomeComponent extends React.Component<SomeComponentProps, SomeComponentState> {
static defaultProps = {
someOptionalProp = 'some default value',
}
method() {
const shouldNotBeOptional = this.props.someOptionalProp;
}
}
How can I assert that this.props.someOptionalProp
is not undefined within the class but is also optional when trying to using the component? 我如何断言this.props.someOptionalProp
在类中不是未定义的,但是在尝试使用组件时也是可选的?
What I've been doing is just ignoring defaultProps
altogether by creating getters that 我一直在做的只是通过创建获取器来完全忽略defaultProps
return `this.props.someOptionalProp || 'the default value'`;
but I'd like to use defaultProps
because my team uses it. 但我想使用defaultProps
因为我的团队正在使用它。
Not really possible as it stands with TS 2.8.3, there are some issues open about it already TS 2.8.3确实不可行,但已经存在一些问题
On react types: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/11640 关于反应类型: https : //github.com/DefinitelyTyped/DefinitelyTyped/issues/11640
On the TS repo: https://github.com/Microsoft/TypeScript/issues/23812 在TS回购上: https : //github.com/Microsoft/TypeScript/issues/23812
Best you can achieve currently I believe is by using the !
我相信您目前可以实现的最好成绩是!
operator to tell the compiler that you know something can't be null 运算符,告诉编译器您知道某些内容不能为null
const shouldNotBeOptional = this.props.someOptionalProp!;
You could use a higher order component (HOC) that will just change the type of the props to be optional where they are present in defaultProps
您可以使用更高阶的组件(HOC),它将仅将props的类型更改为defaultProps
中存在的props的类型。
interface SomeComponentProps {
required: string;
someOptionalProperty: string;
trulyOptional?: string;
}
interface SomeComponentState { /* ... */ }
class SomeComponent extends React.Component<SomeComponentProps, SomeComponentState> {
static defaultProps = {
someOptionalProperty : 'some default value',
}
method() {
const shouldNotBeOptional = this.props.someOptionalProperty;
}
}
type SameTypeOrCustomError<T1, T2> = T1 extends T2 ? T2 extends T1 ? T1 : "Error Different Types": "Error Different Types";
type FilterOptional<T> = Exclude<{ [P in keyof T]: undefined extends T[P]? P: never }[keyof T], undefined>;
type d = FilterOptional<SomeComponentProps>
type PropsWithDefault<TProps extends TDefaults, TDefaults> =
{ [P in Exclude<keyof TProps, keyof TDefaults | FilterOptional<TProps>>]: TProps[P] } &
{ [P in keyof TDefaults | FilterOptional<TProps>]?: TProps[P] };
type ReactProps<T> = T extends React.Component<infer Props, any> ? Props: never;
type ReactState<T> = T extends React.Component<any, infer TState> ? TState: never;
type ChangeReactProps<TComponent extends React.Component<any, any>, TNewProps> = {
new (props: TNewProps, context?: any) : React.Component<TNewProps, ReactState<TComponent>>
};
function withDefaults<T extends { new (...args: any[]) : any, defaultProps: Partial<ReactProps<InstanceType<T>>> }>(ctor: T)
: ChangeReactProps<InstanceType<T>, PropsWithDefault<ReactProps<InstanceType<T>>, T['defaultProps']>> {
return ctor; // we just chage type, we can return the same class
}
const SomeComponent2 = withDefaults(SomeComponent);
let d = <SomeComponent2 required="" /> //ok
let x = <SomeComponent2 required="" trulyOptional="" /> //ok
I use a higher order component with Typescript 2.8 in my codebase: 我在代码库中使用Typescript 2.8的高阶组件:
const withDefaultProps = <P extends object, DP extends Partial<P>>(
defaultProps: DP,
component: React.ComponentType<P>
) => {
type ActualProps = Partial<DP> & Pick<P, Exclude<keyof P, keyof DP>>
component.defaultProps = defaultProps
return component as React.ComponentType<ActualProps>
}
interface IComponentProps {
someOptionalProp: string
}
class SomeComponent extends React.Component<IComponentProps, {}> {
method() {
// this is always defined
const shouldNotBeOptional = this.props.someOptionalProp;
}
}
// when using this like <SomeComponent />, someOptionalProp is optional
export default withDefaultProps(
{ someOptionalProp: 'defaultValue' },
SomeComponent
)
This issue has been discussed and resolved in here . 这个问题已经在这里讨论和解决。 Now you simply can do that: 现在,您只需执行以下操作:
interface Props {
thing: string; // note: not optional within class, but is optional when writing due to the default
}
class Thing extends React.Component<Props> {
static defaultProps = {
thing: 'hello'
}
render() {
console.log(this.props.thing) // strict type from `Props`
// ...
}
}
// ..
<Thing /> // works, thanks to `defaultProps`
It works for me in Typescript 3.1.6 and React 16.5.0 它适用于Typescript 3.1.6和React 16.5.0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.