JSX节点中的TypeScript类型参数

问题描述:

有什么方法可以为在JSX中呈现的组件指定类型参数吗?JSX节点中的TypeScript类型参数

例如,考虑这个组件:

interface SelectorProps<T> { 
    selection: T; 
    options: T[]; 
} 

class Selector<T> extends React.Component<SelectorProps<T>, {}> { 
    // ... 
} 

如果我尝试呈现在JSX这个组件:

<Selector selection="a" options={["a", "b", "c"]} /> 

我得到这些错误:

TS2322:类型“字符串“不能分配给'T'类型。

TS2322:类型'string []'不可分配给类型'T []'。类型'字符串'不是 可分配给类型'T'。

我希望T被推断为string或者某种方式<Selector>指定T=string。有解决方案吗?

我发现的唯一的解决方法是扩展组件,以消除所有类型的参数:

class StringSelector extends Selector<string> { } 
+2

尚未。见https://github.com/Microsoft/TypeScript/issues/6395 –

+0

谢谢,似乎涵盖了这个问题。现在坚持我的'扩展'解决方法。 – Aaron

试试这个。你的接口应该明确声明它所期望的值的类型。这是使用打字稿的关键。如果你真的知道会发生什么,你不应该推断任何事情。

interface SelectorProps { 
    selection: string | number; // This means selection can take in either a string or a number 
    options: string[] | number[]; 
} 

class Selector extends React.Component<SelectorProps, {}> { 
    // ... 
} 
+0

那么如何制作一个可以选择字符串,数字,对象,各种其他接口的“选择器”呢?这就是类型参数的用法,所以你不必使用像'any'这样的模糊类型。 – Aaron

+0

在这种情况下,请使用联合类型。正在修改我的答案以向您展示示例用法@Aaron –

+0

我已经有4种不同的类型,并且在我的应用程序中它们是实际的对象接口,而不是基元。工会不清楚“选择”与“选项”是相同的类型。它要求你在代码中编写断言。它还要求您了解组件将要处理的所有类型。类型参数正是我在这里需要的,但唯一的问题是JSX没有(但)有办法传递它们。 – Aaron

我已经gotton仿制药我在公司创建的一个组成部分的工作,但他们的方式我设法做到这一点并不漂亮。

GenericComponent.tsx:

import * as React from "react"; 

interface IGenericComponentProps<T, S> { 
    propT: T; 
    propS: S; 
} 

interface IGenericComponentState<T, S> {} 

export class GenericComponent<T, S> extends React.Component< 
    IGenericComponentProps<T, S>, 
    IGenericComponentState<T, S> 
    > { 
    public render(): JSX.Element { 
     return (
      <div>Generic component!</div> 
     ); 
    } 

} 

export default GenericComponent; 

GenericComponentImplementation.tsx:

import * as React from "react"; 

// This is the ugly part 
import GenericComponentBase from "./GenericComponent"; 
// This is where you get to define the generic type arguments 
interface StringAndNumberComponentBase { new(): GenericComponentBase<string, number>; }; 
const StringAndNumberComponent = GenericComponentBase as StringAndNumberComponentBase ; 

export default(): JSX.Element => { 
    return (
     <StringAndNumberComponent 
      propT="test" 
      propS={2} 
      /> 
    ); 
}; 

我觉得我得到了这个问题的GitHub在当时这样的信息: https://github.com/Microsoft/TypeScript/issues/3960

interface FooProps<T> { foo: T; } 
class Foo<T> extends React.Component<FooProps<T>, any> { 
    render() { 
    return <div>{ JSON.stringify(this.props.foo) }</div>; 
    } 
} 
type FooBar = new() => Foo<{bar: string}>; 
const FooBar = Foo as FooBar; 

class FooBarContainer extends React.Component<any, any> { 
    render() { 
    return <FooBar foo={{bar: 'works'}} />; 
    } 
} 

FooBarContainer<FooBar foo={{bar: 'works'}} />应呈现:<div>{"bar":"works"}</div>

+1

的完整的上下文有点难受,遵循“foobar的” jarble,但是这真的是比使用'extends'我的解决方法有什么不同? – Aaron