首页 > 解决方案 > 如何使用交集类型默认泛型函数参数

问题描述

我试图弄清楚为什么下面的代码不能像我期望的那样工作。交集类型似乎可以正常工作(在函数内部重新定义时),但是将其用作通用参数类型的默认值则不行。

interface A {
    a: string
}

interface B {
    b: string
}

interface C {
    c: string
}

function returnStuff<T = A & B>(
    optionalReturnFn?: (value: T) => T): (value: T) => T {
    const defaultReturnFn = (value: T) => {
        value.a // <----- why does this a error
        return value
    }
        return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}

function returnStuff2<T extends A & B>(
    optionalReturnFn?: (value: T) => T): (value: T) => T {
    const defaultReturnFn = (value: T) => {
        value.a // <----- while this one does not
        return value
    }
        return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}

const bc: B & C = { b: 'b', c: 'c' } // <--- valid intersection type

// Works as expected when calling fn but DOESN't work as I'd expect internally to fn
returnStuff<B & C>((value) => { 
    return value
 })

// Doesn't work when calling fn but DOES work as expected internally to fn
returnStuff2<B & C>((value) => { 
    return value
 })

如果您想解决这些错误,这里是一个TS Playground 。

更新:我最终添加了一个类型保护并在returnStuff函数定义中使用它。

...
function isDefaultType<DefaultType>(
    record: any,
    keys: string[]
): record is DefaultType {
    return every(keys, (key) => key in record)
}

function returnStuff<T = A & B>(
    optionalReturnFn?: (value: T) => T): (value: T) => T {
    const defaultReturnFn = (value: T) => {
        if(isDefaultType<T>(value, ['a', 'b']) {
            value.a // <----- no longer throws an error
            return value
        }
    }
        return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}

标签: typescript

解决方案


返回东西

T = A & B旁边显示错误,value.a因为您只设置了默认值,但您没有限制Tvia的类型extendsT仍然可以是任何东西,但如果没有指定,它将是A & B. returnStuff<C>(v => v);- 作品。returnStuff(v => v);- 也有效。value.a失败,因为value可以是任何东西,字符串,未定义等。

正确的方法是T extends A & B = A & B

返回东西2

returnStuff2<B & C>不起作用,因为T extends A & B(不是默认值,而是定义的基本类型)需要在anda的联合中缺少的属性。BC


推荐阅读