首页 > 解决方案 > 我可以制作像“可能未定义的字符串”这样的类型吗

问题描述

注意:我已经--strictNullChecks开启

我有这样的功能:

export function ensure<T, F extends T>(maybe: T | undefined, fallback: F): T {
  if (isDefined<T>(maybe)) {
    return maybe
  }

  if (fallback === undefined) {
    throw new Error('Could not ensure a value; please supply a fallback for the given variable')
  }

  return fallback
}

我用它来摆脱undefined可能未定义的值的一部分。

const user = ensure(possiblyUndefinedUser, defaultUser)

我想要以下,

const user = ensure(certainlyDefinedUser, defaultUser)

成为编译时错误。即,我希望将此函数与编译器认为具有值的值一起使用是非法的。(这将迫使我正确输入我的函数,见下文)

我已经尝试了一些关于泛型参数的变体,以获得一个类型的T | undefinedT不能分配给它的类型。我意识到这可能是不可能的,但我想我会咨询社区而不是继续努力。


我的目标是:如果我想通过类似isNilor的函数传递参数ensure,那么我想被迫将参数类型更改为可选。如果一个参数不是可选的,那么我应该 100% 确信不需要对它进行空检查。

标签: typescript

解决方案


如果第一个参数不能未定义,我们可以使用条件类型来触发第二个参数的错误。

function isDefined<T>(v: T) : v is Exclude<T, undefined> {
    return !!v;
}

export function ensure<T, F extends (undefined extends T ? T : 'First param can\'t be undefined')>(maybe: T, fallback: F): Exclude<T, undefined> {
    if (isDefined<T>(maybe)) {
        return maybe
    }

    if (fallback === undefined) {
        throw new Error('Could not ensure a value; please supply a fallback for the given variable')
    }
    //We need a type assertion here as F tehnically might not extend T
    return fallback as any;
}

declare var defaultUser: string|undefined;
declare var possiblyUndefinedUser: string| undefined
const user = ensure(possiblyUndefinedUser, defaultUser) //ok

declare var certainlyDefinedUser: string;
const user2 = ensure(certainlyDefinedUser, defaultUser); //error

Playground链接您需要手动选择严格的空检查。


推荐阅读