繁体   English   中英

React-Typescript:如何输入默认道具?

[英]React-Typescript: How do I type a default prop?

假设我有这个组件类:

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;
  }
}

我如何断言this.props.someOptionalProp在类中不是未定义的,但是在尝试使用组件时也是可选的?

我一直在做的只是通过创建获取器来完全忽略defaultProps

return `this.props.someOptionalProp || 'the default value'`;

但我想使用defaultProps因为我的团队正在使用它。

TS 2.8.3确实不可行,但已经存在一些问题

关于反应类型: https : //github.com/DefinitelyTyped/DefinitelyTyped/issues/11640

在TS回购上: https : //github.com/Microsoft/TypeScript/issues/23812

我相信您目前可以实现的最好成绩是! 运算符,告诉编译器您知道某些内容不能为null

const shouldNotBeOptional = this.props.someOptionalProp!;

您可以使用更高阶的组件(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 

我在代码库中使用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
)

这个问题已经在这里讨论和解决。 现在,您只需执行以下操作:

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`

它适用于Typescript 3.1.6和React 16.5.0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM