Typescript 类型';{name:string;}&;拾取<;TProps,排除<;“TProps的按键”;名称“&燃气轮机&燃气轮机';不可分配给类型';TProps&x27;

Typescript 类型';{name:string;}&;拾取<;TProps,排除<;“TProps的按键”;名称“&燃气轮机&燃气轮机';不可分配给类型';TProps&x27;,typescript,Typescript,我正在尝试创建一个可以在没有提供道具的情况下设置道具的 如果需要,我可以提供该代码,但它附带了一些使代码复杂化的代码,实际上与我遇到的错误没有任何关系 因此,我创建了一个MVCE,它以更清晰的方式再现了问题: interface RequiredProps { name?: string; } const setDefaults = <TProps extends RequiredProps>(props: TProps) => { const {

我正在尝试创建一个可以在没有提供道具的情况下设置道具的

如果需要,我可以提供该代码,但它附带了一些使代码复杂化的代码,实际上与我遇到的错误没有任何关系

因此,我创建了一个MVCE,它以更清晰的方式再现了问题:

interface RequiredProps {
    name?: string;
}

const setDefaults = <TProps extends RequiredProps>(props: TProps) => {
    const {
        name: nameProp,
        ...rest
    } = props;

    const newProps: TProps = {
        name: (nameProp != null) ? nameProp : "Alice",
        ...rest
    };

    return newProps;
};
我得到了一个错误:

因此,我用抓取我知道应该存在的字段,并将其余字段放入
…rest

然后我构造
newProps
组合我默认的字段和
…rest

问题是,在这一点上,我得到了错误:

Type
{name:string;}&Pick
不能分配给Type
TProps

对我来说,读作“TProps,不包括name属性,加上name字段,不能分配给TProps”,这让我有点困惑

我想知道它是否不喜欢
name
现在是
string
而不是
string?
。问题是,
string
可分配给
string?
,但我还是尝试修改代码

const newProps: TProps = {
    name: ((nameProp != null) ? nameProp : "Alice") as string | undefined,
    ...rest
};
但正如预期的那样,这没有什么区别

我注意到在错误消息中,它说类型是
{name:string;}
,而不是
{name?:string;}
,因此我对代码进行了更改,尝试解决这个问题

const newRequiredProps: { name?: string } = {
    name: (nameProp != null) ? nameProp : "Alice"
};

const newProps: TProps = {
    ...newRequiredProps,
    ...rest
};
错误消息现在显示了“更正确”的类型,但基本上保持不变

Type
{name?:string;}&Pick
不能分配给Type
TProps

我确实发现了一个有效的方法,那就是使用
as
强制输入:

const newProps: TProps = {
    name: (nameProp != null) ? nameProp : "Alice",
    ...rest
} as TProps;
但这感觉就像我只是在掩盖打字问题,而不是真正解决它


有没有办法让类型系统理解我要做的事情,而不是强迫它接受类型?

编译器很难验证泛型类型上复杂的条件类型操作。只要您确信不会发生这样疯狂的事情,您正在执行的类型断言是完全可以接受的:

type PossiblyBob = { name?: "Bob" };
const possiblyBob: PossiblyBob = Math.random() < 0.5 ? {} : { name: "Bob" };
setDefaults(possiblyBob);
这或多或少是一样的(只要
props.name
实际上没有设置为
未定义的值
)。但是,缺少类型错误是一种技巧。for
Object.assign()
返回其输入类型的名称,即。最终,它们可能会返回
Object.assign()
的返回类型,然后您也会遇到相同的类型断言问题

所以我想我的建议是离开类型断言并继续


希望有帮助;祝你好运

感谢您的关注和解释。
type PossiblyBob = { name?: "Bob" };
const possiblyBob: PossiblyBob = Math.random() < 0.5 ? {} : { name: "Bob" };
setDefaults(possiblyBob);
const setDefaults: TProps = <TProps extends RequiredProps>(props: TProps) => {            
  const newProps = Object.assign({ name: "Alice" }, props);      
};