【问题标题】:TypeScript Conditional Generic Interface as Parameter (Array or Object, based on boolean)TypeScript 条件通用接口作为参数(数组或对象,基于布尔值)
【发布时间】:2019-01-04 07:45:31
【问题描述】:

我有一个函数应该能够接收两种相似类型作为参数。取决于props.multitrue 还是false

问题是它仍然允许我通过value = []multi = false。我怎样才能摆脱它?

interface PropsSingle<T> {
    value: T,
    multi: false
}

interface PropsMulti<T> {
    value: T[],
    multi: true
}

function foo<T>(props: PropsSingle<T> | PropsMulti<T>) {
    if(props.multi) {
        let arr = props.value // type detection works fine
    } else {
        let obj = props.value // type detection works fine
    }
}

foo({multi: true, value: []}) // works as expected
foo({multi: true, value: {}}) // throws error as expected
foo({multi: false, value: {}}) // works as expected
foo({multi: false, value: []}) // THIS SHOULD THROW AN ERROR

我已经尝试过foo&lt;T extends object&gt;(...)foo&lt;T extends {[key: string]: any}&gt;(...)

我发现的唯一一种解决方案/解决方法是:

interface PropsSingle<T> {
    value: T extends any[] ? never : T,
    multi: false
}

但这对我来说很奇怪。

为什么我不能限制function foo的类型?

【问题讨论】:

    标签: typescript generics type-inference typescript-generics


    【解决方案1】:

    原因很简单,没有什么可以阻止PropsSingle 中的T 成为any[]。并且没有简单的方法让 typescript 知道泛型参数不能扩展给定类型,我们只能指定 T 扩展的内容。

    您的解决方案应该可行,我通常在函数上添加约束并使用字符串文字类型在处理这种情况时提供更具暗示性的错误消息:

    interface PropsSingle<T> {
        value: T,
        multi: false
    }
    
    interface PropsMulti<T> {
        value: T[],
        multi: true
    }
    
    type ErrorIf<T, U, TError> = T extends U ? TError : {} 
    
    function foo<T>(props: (PropsSingle<T> & ErrorIf<T, any[], "Argument to PropsSingle can't be []")| PropsMulti<T>) {
        if(props.multi) {
            let arr = props.value // type detection works fine
        } else {
            let obj = props.value // type detection works fine
        }
    }
    
    foo({multi: true, value: []}) // works as expected
    foo({multi: true, value: {}}) // throws error as expected
    foo({multi: false, value: {}}) // works as expected
    foo({multi: false, value: []}) // Error Type '{ multi: false; value: undefined[]; }' is not assignable to type '"Argument to PropsSingle can't be []"'.
    

    【讨论】:

    • 谢谢 :) 。我想到了类似foo&lt;T, M extends boolean&gt;(props: M extends true ? PropsSingle&lt;T&gt; : PropsMulti&lt;T&gt;) 或类似的东西。但我无法让它工作。
    • @BenjaminM 我认为这不会起作用,除非您明确指定 M 和 T,您可能希望避免这种情况。我在 SO 上多次看到类似的问题,不幸的是我没有看到更好的解决方案
    猜你喜欢
    • 1970-01-01
    • 2018-12-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 2019-06-28
    • 2018-09-06
    相关资源
    最近更新 更多