问题描述
我不知道如何使用Typescript为我的组件设置默认属性值.
I can't figure out how to set default property values for my components using Typescript.
这是源代码:
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>
);
}
}
当我尝试使用这样的组件时:
And when I try to use the component like this:
ReactDOM.render(<PageComponent />, document.getElementById("page"));
我收到一条错误消息,指出缺少属性foo
.我想使用默认值.我也曾尝试在组件内部使用static defaultProps = ...
,但是我怀疑它没有任何作用.
I get an error saying property foo
is missing. I want to use the default value. I've also tried to use static defaultProps = ...
inside the component, but it had no effect as I suspected.
src/typescript/main.tsx(8,17): error TS2324: Property 'foo' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...'.
如何使用默认属性值?我公司使用的许多JS组件都依赖于它们,而不选择不使用它们.
How can I use default property values? Many JS components my company uses rely on them and not using them is not a choice.
推荐答案
带有类组件的默认道具
使用static defaultProps
是正确的.您还应该使用接口(而不是类)作为道具和状态.
Default props with class component
Using static defaultProps
is correct. You should also be using interfaces, not classes, for the props and state.
更新2018/12/1 :随着时间的推移,TypeScript改进了与defaultProps
相关的类型检查.继续阅读以获取最新和最佳用法,直到较旧的用法和问题为止.
Update 2018/12/1: TypeScript has improved the type-checking related to defaultProps
over time. Read on for latest and greatest usage down to older usages and issues.
TypeScript特别是添加了对defaultProps
的支持,以使类型检查按预期进行.示例:
TypeScript specifically added support for defaultProps
to make type-checking work how you'd expect. Example:
interface PageProps {
foo: string;
bar: string;
}
export class PageComponent extends React.Component<PageProps, {}> {
public static defaultProps = {
foo: "default"
};
public render(): JSX.Element {
return (
<span>Hello, { this.props.foo.toUpperCase() }</span>
);
}
}
可以在不传递foo
属性的情况下进行渲染和编译:
Which can be rendered and compile without passing a foo
attribute:
<PageComponent bar={ "hello" } />
请注意:
-
foo
不是 标记为可选的(即foo?: string
),即使它不是JSX属性也是必需的.标记为可选意味着它可能是undefined
,但是实际上它永远不会是undefined
,因为defaultProps
提供了默认值.认为它类似于您可以将函数参数标记为可选,也可以标记为默认值,但不能同时标记为两者,但这两者都意味着调用不需要指定值. TypeScript 3.0+以类似的方式对待defaultProps
,这对于React用户来说真的很酷! -
defaultProps
没有显式类型注释.推断出它的类型,并由编译器使用它来确定需要哪些JSX属性.您可以使用defaultProps: Pick<PageProps, "foo">
确保defaultProps
与PageProps
的子集匹配.关于此警告的更多信息是此处解释. - 这需要
@types/react
版本16.4.11
才能正常工作.
foo
is not marked optional (iefoo?: string
) even though it's not required as a JSX attribute. Marking as optional would mean that it could beundefined
, but in fact it never will beundefined
becausedefaultProps
provides a default value. Think of it similar to how you can mark a function parameter optional, or with a default value, but not both, yet both mean the call doesn't need to specify a value. TypeScript 3.0+ treatsdefaultProps
in a similar way, which is really cool for React users!- The
defaultProps
has no explicit type annotation. Its type is inferred and used by the compiler to determine which JSX attributes are required. You could usedefaultProps: Pick<PageProps, "foo">
to ensuredefaultProps
matches a sub-set ofPageProps
. More on this caveat is explained here. - This requires
@types/react
version16.4.11
to work properly.
在TypeScript 3.0实现对defaultProps
的编译器支持之前,您仍然可以使用它,并且它在运行时可与React一起工作100%,但由于TypeScript在检查JSX属性时仅考虑了props,因此您必须将props标记为?
的默认值是可选的.示例:
Before TypeScript 3.0 implemented compiler support for defaultProps
you could still make use of it, and it worked 100% with React at runtime, but since TypeScript only considered props when checking for JSX attributes you'd have to mark props that have defaults as optional with ?
. Example:
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>
);
}
}
请注意:
- 用
Partial<>
注释defaultProps
是个好主意,以便对您的道具进行类型检查,但是您不必为每个必需的属性都提供默认值,这是没有意义的,因为必需的属性应该永远不需要默认值. - 使用
strictNullChecks
时,this.props.foo
的值将为possibly undefined
,并且需要非空声明(即this.props.foo!
)或类型保护(即if (this.props.foo) ...
)来删除undefined
.这很烦人,因为默认的prop值意味着它实际上永远不会被定义,但是TS不能理解这一流程.这是TS 3.0添加了对defaultProps
的显式支持的主要原因之一.
- It's a good idea to annotate
defaultProps
withPartial<>
so that it type-checks against your props, but you don't have to supply every required property with a default value, which makes no sense since required properties should never need a default. - When using
strictNullChecks
the value ofthis.props.foo
will bepossibly undefined
and require a non-null assertion (iethis.props.foo!
) or type-guard (ieif (this.props.foo) ...
) to removeundefined
. This is annoying since the default prop value means it actually will never be undefined, but TS didn't understand this flow. That's one of the main reasons TS 3.0 added explicit support fordefaultProps
.
这工作原理相同,但是您没有Partial
类型,因此只需忽略Partial<>
,或者为所有必需的道具提供默认值(即使永远不会使用这些默认值),或者完全忽略显式类型注释
This works the same but you don't have Partial
types, so just omit Partial<>
and either supply default values for all required props (even though those defaults will never be used) or omit the explicit type annotation completely.
您也可以在功能组件上使用defaultProps
,但是必须在FunctionComponent
(版本16.7.2
之前的@types/react
中的StatelessComponent
)界面上键入函数,以便TypeScript知道defaultProps
在功能上:
You can use defaultProps
on function components as well, but you have to type your function to the FunctionComponent
(StatelessComponent
in @types/react
before version 16.7.2
) interface so that TypeScript knows about defaultProps
on the function:
interface PageProps {
foo?: string;
bar: number;
}
const PageComponent: FunctionComponent<PageProps> = (props) => {
return (
<span>Hello, {props.foo}, {props.bar}</span>
);
};
PageComponent.defaultProps = {
foo: "default"
};
请注意,您不必在任何地方使用Partial<PageProps>
,因为在TS 2.1+中已经将FunctionComponent.defaultProps
指定为部分.
Note that you don't have to use Partial<PageProps>
anywhere because FunctionComponent.defaultProps
is already specified as a partial in TS 2.1+.
另一种不错的选择(这是我使用的方法)是破坏您的props
参数并直接分配默认值:
Another nice alternative (this is what I use) is to destructure your props
parameters and assign default values directly:
const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
return (
<span>Hello, {foo}, {bar}</span>
);
};
那么您根本不需要defaultProps
!请注意,如果您在功能组件上 do 提供defaultProps
,它将优先于默认参数值,因为React始终会显式传递defaultProps
值(因此参数绝不会是未定义的,因此默认参数是从不使用.)因此,您可以使用其中一个,而不能同时使用.
Then you don't need the defaultProps
at all! Be aware that if you do provide defaultProps
on a function component it will take precedence over default parameter values, because React will always explicitly pass the defaultProps
values (so the parameters are never undefined, thus the default parameter is never used.) So you'd use one or the other, not both.
这篇关于使用TypeScript在React组件中的默认属性值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!