![](/img/trans.png)
[英]TypeScript - specify type while object destructuring with alias
[英]Typescript type error while destructuring on empty object with default values?
我正在用ReactJS + Typescript编写一个Web应用程序。 我有一个如下定义的功能组件。
我的问题是:在道具中,属性exercise
,父组件传递对象,无论是初始化空的,或者我指定,某种类型的Exercise
。 然后Typescript引发以下错误:
[ts] Property 'description' does not exist on type '{} | Exercise'
[ts] Property 'title' does not exist on type '{} | Exercise'
我如何重构它,以便如果对象确实为空,它将使用默认值,否则使用传递的值?
编辑:添加了我使用的其他道具
type Exercise = {
description: string
id: string
muscles: string
title: string
}
type Props = {
category: string
children?: never
exercise: {} | Exercise
exercises: Array<[string, Exercise[]]>
onSelect: (id: string) => void
}
const Exercises = ({
exercises,
category,
onSelect,
exercise: {
description = 'Please select an exercise',
title = 'Welcome!'
}
}: Props) => (
<Grid container>
<Grid item sm>
{/* Some stuff going on with exercises, category and onSelect */ }
</Grid>
<Grid item sm>
<Paper>
<Typography variant="h4">{title}</Typography>
<Typography variant="subtitle1">{description}</Typography>
</Paper>
</Grid>
</Grid>
)
我认为类似的东西应该起作用
type Exercise = {
description: string
id: string
muscles: string
title: string
}
type Props = {
exercise: Partial<Exercise>
}
const Exercises = (props: Props) => {
const exercice = {
description:'Please select an exercise',
title: 'Welcome!',
...props.exercise
}
return (
<Grid container>
<Grid item sm>
<Paper>
<Typography variant="h4">{exercice.title}</Typography>
<Typography variant="subtitle1">{exercice.description}</Typography>
</Paper>
</Grid>
</Grid>
)
}
编辑:对齐代码
因此,总的来说,我认为您的API设计不适用于此组件。 您基本上是在将练习实体误用为某些默认的“欢迎消息”,这很容易导致该组件的使用者使用。
我要做的是在没有练习时提供这些介绍性默认值,但绝对不会使用练习道具来分配这些默认值。
接下来,不要使用{}
,它不是空对象(您可以像下面的https://github.com/Hotell/rex-tils/blob/master/src/guards/types.ts#L39那样定义空对象) 。 在TS 3.0之前,它曾经是底部类型(现在unknown
是底部类型)。 这是什么意思? {}
可以是null / undefined以外的任何值:
// all of this is valid !
let foo: {} = 1231
foo = true
foo = { baz: 'bar' }
foo = [1,2,3]
另外,如果您真的想支持将“空”非原始数据类型传递给组件,则最好使用null
:
type Props = {
category: string
children?: never
// Maybe type
exercise: null | Exercise
exercises: [string, Exercise[]][]
onSelect: (id: string) => void
}
无论如何,如果您确实想保持API原样。 您有以下选择:
const defaultExercise = {
description: 'Please select an exercise',
title: 'Welcome!',
} as Exercise
const Exercises = ({ exercises, category, onSelect, exercise }: Props) => {
// $ExpectType Exercise
const { title, description } = exercise ? exercise : defaultExercise
return <>your markup</>
}
现在,尽管这样做有效,但给您错误的假设。 因为您的exercise
可能只是部分exercise
(如果使用默认设置),则可能会导致运行时错误。 您将需要通过警卫(如果是三元)来进一步缩小类型。
您可以通过一些类型映射在类型级别上改善这种情况:
// $ExpectType { description: string, title: string, id?: string, muscles?: string }
const defaultExercise = {
description: 'Please select an exercise',
title: 'Welcome!',
} as Partial<Exercise> & Required<Pick<Exercise, 'description' | 'title'>>
如果您要在组件中使用id
或muscles
,则使用该类型,您将获得正确的类型,因为它们可能是未定义的,从而正确地反映了我们的三元
const {
title, //$ExpectType string
description, //$ExpectType string
id, //$ExpectType string | undefined
} = exercise ? exercise : defaultExercise
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.