在ReactJS中,我通常使用这种模式的destructurnig-props(我想这是很习惯的(:
export default function Example({ ExampleProps }) {
const {
content,
title,
date,
featuredImage,
author,
tags,
} = ExampleProps || {};
我可以在销毁时添加默认值,这增加了一些安全性:
export default function Example({ ExampleProps }) {
const {
content = "",
title = "Missing Title",
date = "",
featuredImage = {},
author = {},
tags = [],
} = ExampleProps || {};
但现在我切换到TypeScriptstrict
模式,我有一段相当艰难的时间。我的道具是由GraphQl codegen键入的,实际上所有属性都封装在Maybe<T>
类型中,所以当展开时,会有类似的actualValue | null | undefined
。
默认值({ maybeUndefined = ""} = props)
可以在值为undefined
的情况下保存我,但null
的值会通过,所以TS编译器很烦人,我的代码会导致很多:
tags?.nodes?.length // etc…
这让我有点紧张,因为《可选链接的成本》一文(尽管我不知道2021年它的回报率如何(。我还听说CCD_ 7运算符的过度使用被称为";代码气味";。
是否有一种模式,可能利用了??
运算符,可以让TS编译器满意,并且可以删除至少一些very?.long?.optional?.chains
我看到了两个可能的选项:
-
逐属性执行零合并属性,或
-
使用实用程序功能
逐个属性
相当缓慢(我是一个缓慢的开发人员(:
// Default `ExampleProps` here −−−−−−−−−−−−−−−vvvvv
export default function Example({ ExampleProps = {} }) {
// Then do the nullish coalescing per-item
const content = ExampleProps.content ?? "";
const title = ExampleProps.title ?? "Missing Title";
const date = ExampleProps.date ?? "";
const featuredImage = ExampleProps.featuredImage ?? {},
const author = ExampleProps.author ?? {},
const tags = ExampleProps.tags ?? [];
// ...
效用函数
或者,使用以下实用程序函数将null
值(编译时和运行时(转换为undefined
,这样在对结果进行析构函数时就可以使用析构函数默认值。类型部分相当简单:
type NullToUndefined<Type> = {
[key in keyof Type]: Exclude<Type[key], null>;
}
那么效用函数可能是这样的:
function nullToUndefined<
SourceType extends object,
ResultType = NullToUndefined<SourceType>
>(object: SourceType) {
return Object.fromEntries(
Object.entries(object).map(([key, value]) => [key, value ?? undefined])
) as ResultType;
}
或者像这样(可能在运行时更高效(:
function nullToUndefined<
SourceType extends object,
ResultType = NullToUndefined<SourceType>
>(object: SourceType) {
const source = object as {[key: string]: any};
const result: {[key: string]: any} = {};
for (const key in object) {
if (Object.hasOwn(object, key)) {
result[key] = source[key] ?? undefined;
}
}
return result as ResultType;
}
请注意,Object.hasOwn
是非常新的,但很容易填充。或者您可以使用Object.prototype.hasOwn.call(object, key)
。
(在nullToUndefined
中的这两种情况下,我对类型断言都有点反复无常。对于这样的小型实用函数,我认为只要输入和输出定义良好,这是一个合理的折衷方案。(
然后:
export default function Example({ ExampleProps }) {
const {
content = "",
title = "Missing Title",
date = "",
featuredImage = {},
author = {},
tags = [],
} = nullToUndefined(ExampleProps || {});
// ^^^^^^^^^^^^^^^^−−−−−−−−−−−−−−−−−−^
// ...
游乐场链接