2016-05-17 52 views
41

我无法弄清楚如何使用我的打字原稿设置组件的默认属性值作出反应的组成部分。默认属性数值的使用打字稿

这是源代码:

class PageState 
{ 
} 

export class PageProps 
{ 
    foo: string = "bar"; 
} 

export class PageComponent extends React.Component<PageProps, PageState> 
{ 
    public render(): JSX.Element 
    { 
     return (
      <span>Hello, world</span> 
     ); 
    } 
} 

当我尝试使用这样的组件:

ReactDOM.render(<PageComponent />, document.getElementById("page")); 

我得到一个错误说属性foo丢失。我想使用默认值。我也尝试在组件内部使用static defaultProps = ...,但它没有影响,因为我怀疑。

src/typescript/main.tsx(8,17): error TS2324: Property 'foo' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...'. 

如何使用默认属性值?我公司使用的许多JS组件都依赖于它们,而不使用它们不是一种选择。

+0

'static defaultProps' is correct。你可以发布该代码吗? – Aaron

回答

95

使用static defaultProps是正确的。您还应该为道具和状态使用接口,而不是类,并使用?标记可选属性。

更新打字稿2.1:现在TS支持partial types这是一个好主意,用Partial<Props>注释为您defaultProps这样你可以只是你可选道具提供默认值,而TS抱怨你的defaultProps缺少必需的道具。

这里有一个完整的例子:(这通过省略Partial<>并为所有需要的道具提供的默认值,即使你真的只是想为可选道具默认工作前打字稿2.1)

interface PageProps { 
    foo?: string; 
    bar: number; 
} 

export class PageComponent extends React.Component<PageProps, {}> { 
    public static defaultProps: Partial<PageProps> = { 
     foo: "default" 
    }; 

    public render(): JSX.Element { 
     return (
      <span>Hello, world</span> 
     ); 
    } 
} 

更新Stateless Functional Components

您可以在功能COMPON使用defaultProps经济需求为好,但你必须键入你的函数的StatelessComponent接口,以便打字稿知道的功能有关defaultProps

interface PageProps { 
    foo?: string; 
    bar: number; 
} 

const PageComponent: StatelessComponent<PageProps> = (props) => { 
    return (
    <span>Hello, {props.foo}, {props.bar}</span> 
); 
}; 

PageComponent.defaultProps = { 
    foo: "default" 
}; 

请注意,你不必因为StatelessComponent.defaultProps已经被指定为使用Partial<PageProps>任何地方部分在TS 2.1+。

另一种不错的选择(这是我使用)是解构你props参数并直接分配默认值:

const PageComponent: StatelessComponent<PageProps> = ({foo = "default", bar}) => { 
    return (
    <span>Hello, {foo}, {bar}</span> 
); 
}; 

那么你不需要defaultProps了!请注意,如果你功能组件就会接管默认参数值的优先级上提供defaultProps,因为阵营总是明确地传递defaultProps值(这样的参数是从来没有定义,因此从未使用默认参数。)因此,你会使用其中一种,而不是两种。

+0

我ctrl + c/ctr + v'd你的代码(并修复了不应该在那里的分号),它给了我同样的错误:src/typescript/main.tsx(8,17):error TS2324 :在'IntrinsicAttributes&IntrinsicClassAttributes &PageProps&{children ?: ReactEle ...'类型中缺少属性'foo'。 – Tom

+1

错误听起来像你正在使用''而不通过'foo'道具。你可以在你的界面中使用'foo?:string'来使它成为可选的。 – Aaron

+0

是的,因为我需要它使用defaultProps中指定的默认值 - 当我在使用它的地方传递道具时,它会被覆盖,不是吗? – Tom

1

从@pamelus上公认的答案评论:

You either have to make all interface properties optional (bad) or specify default value also for all required fields (unnecessary boilerplate) or avoid specifying type on defaultProps.

其实你可以使用打字稿的interface inheritance。结果代码只是稍微冗长一点。

interface OptionalGoogleAdsProps { 
    format?: string; 
    className?: string; 
    style?: any; 
    scriptSrc?: string 
} 

interface GoogleAdsProps extends OptionalGoogleAdsProps { 
    client: string; 
    slot: string; 
} 


/** 
* Inspired by https://github.com/wonism/react-google-ads/blob/master/src/google-ads.js 
*/ 
export default class GoogleAds extends React.Component<GoogleAdsProps, void> { 
    public static defaultProps: OptionalGoogleAdsProps = { 
     format: "auto", 
     style: { display: 'block' }, 
     scriptSrc: "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" 
    }; 
10

随着打字稿2.1+,使用部分< T>,而不是让你的界面特性可选。

export interface Props { 
    obj: Model, 
    a: boolean 
    b: boolean 
} 

public static defaultProps: Partial<Props> = { 
    a: true 
};