簡體   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