TypeScript打字问题(与(P)React有关)

Nat*_*sha 5 types typescript reactjs typescript-typings

[编辑:我已经简化了原来的问题]

假设我要严格按照下列方式来定义UI组件(以下行,不得以任何方式改变-这将改变以下线的任何解决方案是不坦白我找...例如只写一个解决方案render({ name: 'World' }) 是不是一个选择...非null断言运算符也不...没有使用currying或生成器模式或诸如withDefaultProps辅助函数之类的东西...等等....这些只是实际的解决方法(但仍很容易使用)问题如下:

// please do not change anything in this code snippet

type HelloWorldProps = {
  name?: string
}

export default component<HelloWorldProps>({
  displayName: 'HelloWorld',
  defaultProps: { name: 'World' },

  render(props) {
    // the next line shall NOT throw a compile error
    // that props.name might be undefined
    return `HELLO ${props.name.toUpperCase()}`

    // [Edit] Please ignore that the function returns a string
    // and not a virtual element or whatever - this is not important here.
    // My question is about a TypeScript-only problem,
    // not about a React problem.

    // [Edit] As it has been caused some misunderstanding:
    // The type of argument `props` in the render function shall
    // basically be the original component props type plus (&) all
    // properties that are given in `defaultProps` shall be required now.
    // Those optional props that have no default value shall still
    // be optional. If ComponentType is the original type of the component
    // properties and the type of the `defaultProps` is D then
    // the type of the first argument in the render function shall
    // be: ComponentProps & D

     // [Edit] As it seems not to be 100% clear what I am looking for:
     // The problem is mainly because the function "component" depends basically
     // on two types: One is the type of the component props the other is
     // is the type of the default props. AFAIK it's currently only possible in
     // TypeScript to infer either both of them or none of them (or use
     // default types for the type variables - which is not very useful here
     // as the defaults are {}). But I only want to declare ONE type
     // (HelloWorldProps).
     // All workarounds that I know of are either to explictly declare both
     // types or split the single function "component" into two or more
     // functions - then you do not have that problem any more,
     // but then you have to change the syntax and that is exactly
     // what I do NOT want to do (a fact that is the most important
     // part of the  whole question):

     // [this is not the solution I am looking for]
     // export default component<HelloWorldProps>('HelloWorld')({
     //   defaultProps: {...},
     //   render(props) {...}
     // })

     // [this is not the solution I am looking for]
     // export default component<HelloWorldProps>('HelloWorld')
     //   .defaultProps({...})
     //   .render(props => ...) // `render` is the function component
     //                         // creator is this builder pattern

     // [this is not the solution I am looking for]
     // export default component<HelloWorldProps>({
     //   displayName: 'HelloWorld',
     //   render: withDefaultProps(defaultProps, props => { ... })
     // })

     // [this is not the solution I am looking for]
     // type HelloWorldProps = {...}
     // const defaultProps: Partial<HelloWorldProps> = {...}
     // export default component<HelloWorldProps, typeof defaultProps>({...})

     // [this is not the solution I am looking for]
     // return `HELLO ${props.name!.toUpperCase()}`

     // [this is not the solution I am looking for]
     // render(props: HelloWorldProps & typeof defaultProps) {...}   

     // [this is not the solution I am looking for]
     // render({ name = 'HelloWorld' }) {...}
  }
})
Run Code Online (Sandbox Code Playgroud)

我到底该如何键入函数component和类型ComponentConfig才能使上述代码正常工作?

function component<...>(config: ComponentConfig<...>): any {
  ...
}
Run Code Online (Sandbox Code Playgroud)

请在此处找到无效的(!)演示:

» 演示

[编辑]也许现在还不可能。我认为如果为TS编译器实现此功能应该是可能的。 https://github.com/Microsoft/TypeScript/issues/16597

Ped*_*tes 2

经过几天的讨论和研究,鉴于您的限制,不可能解决您的问题。

正如您在问题中指出的那样:

[编辑]也许目前这是不可能的。我想如果TS编译器能实现这个功能应该是可能的。https://github.com/Microsoft/TypeScript/issues/16597

TS 不会在函数/类声明时推断泛型。您的问题的想法与问题 16597相同:

// issue example
class Greeter<T, S> {
    greeting: T;
    constructor(message: T, message2: S) {
        this.greeting = message;
    }

}

// your issue
function component<P extends {} = {}>(config: ComponentConfig<P>): any {
  return null
}

// generalizing
const function<SOME_GIVEN_TYPE, TYPE_TO_BE_INFERED?>() {
  // TYPE_TO_BE_INFERED is defined inside de function/class.
}
Run Code Online (Sandbox Code Playgroud)