TypeScript检查空字符串

43

TypeScript是否有一种方法可以静态检查空字符串?是否有一种方法可以静态地要求将非空字符串传递给函数?

let fn = function(a:string){

};

fn('');
或者
let a = '';
fn(a);

TS 能帮助我们吗?

7个回答

35

我认为这是你只使用输入系统(而不是拥有一个'nonEmptyString'类)所能获得的最接近的结果。

type nonEmptyString = never; // Cannot be implicitly cast to
function isNonEmptyString(str: string): str is nonEmptyString {
    return str && str.length > 0; // Or any other logic, removing whitespace, etc.
}

测试一下:

let fn = function(a: nonEmptyString) {

}

let someStr = '';
if (isNonEmptyString(someStr)) {
    fn(someStr); // Valid
} else {
    fn(someStr); // Compile error
}

不幸的是,由于nonEmptyStringnever类型,所以您最终会得到疣,这意味着您需要将nonEmptyString显式转换回string.

let fn = function(a: nonEmptyString) {
    let len = a.length; // Invalid
    let len2 = (<string>a).length; // Valid
    let str = a + 'something else'; // Valid (str is now typed as string)
}

一个可能的解决方案是:

type nonEmptyString = string & { __nonEmptyStr: never };

这样可以缓解需要显式转换为字符串的问题(以上三个测试都有效),但会污染类型,引入 __nonEmptyStr(如果被引用,则为 undefined)。


也许我们可以要求一个具有 toString 方法的对象,那也可以工作,只是一种不同类型的解决方案。 - Alexander Mills
除了我认为所有对象都有一个toString方法...嗯。 - Alexander Mills
为什么不直接使用string类型呢: const isNotBlank = (str?: string|null): str is string => (str !== undefined && str !== null && str.trim().length > 0)? 真诚提问 - 这种方法有何问题?。 - Anoiny
1
@Anoiny 这个方法可以用来检查字符串是否为空,但是如果你想定义一个需要非空字符串的函数,该怎么使用呢? - Rob

22
您可以在特定情况下使用这个技巧:
function fn<T extends string>(a: T extends '' ? never : T) {
  // But TypeScript won't know here that !!a === true
}

fn(''); // Error
fn('foo'); // No error

5
这道问题只有一个正确答案。它完全可行且不涉及静态类型检查。 - Jack Steam
有没有办法针对接口而不是函数参数来实现这个?例如:type NonEmptyString = ....; interface Props { content: NonEmptyString; } - JaKXz
2
你可以将其转换为实用程序类型 type NonEmptyString<T> = T extends '' ? never : T - Pyrolistical

3
你可以使用重载的方式来处理这个问题,例如给""设置一个错误的返回类型,这样当你在其它地方使用时就会立即报错:
type MyFnType = {
  (a: "") => never;
  (a: string) => whatever;
}

function fn: MyFnType = ...

由于某种原因,上述语法无法编译,但我同意解决方案。 - Srivathsa Harish Venkataramana
这个解决方案是可行的,但正如已经指出的那样,这个例子无法编译。这里有一个可以编译的例子:https://codesandbox.io/s/jnbu6 - 它实现了函数重载,例如 function fn(s: ''): never; function fn(s: string): string; function fn(s: string | '') {/* 在这里执行真正的工作 */} - Henry Blyth

3

解决方法

type NonEmpty<T extends string = string> = T extends '' ? never : T
// or extends NonNullable
type NonNull<T> = T extends string ? NonEmpty<T> : NonNullable<T>

注意!它只适用于字面类型泛型类型,不适用于基本类型string

playground


事实上,如果不考虑历史因素,我更倾向于将NonNull命名为Valuable - abitwhy Wei
但是 const foo: NonEmpty = '' 将导致 foo 的类型为 string - craigpatik

-3

您可以使用!a来检查a是否为空字符串。


7
不是一个答案,因为问题涉及TypeScript中的静态类型检查,而不是JavaScript中的运行时检查。 - belkka

-4
以下代码片段控制字符串是否为空,即使有空格也是如此。
private checkRequired(text:string){
        if(text == null) return false;
        let n = text.length; 
        for (let i = 1; i < n; i++){
            if (text[i] !== " "){
                return true;
            }
        }  
        return false;
      }

if(this.checkRequired("bla bla blast")){
 ... do your stuff 
}

1
请不要使用这个。它缺少对未定义的检查,而且你可以调用.trim()方法来检查每个字符是否为空格,看结果是否长度为0。是的,这样做会慢一些,但更易读。然而,一个带有空格的字符串真的是空的吗?OP没有指明。 - CiriousJoker

-5
在项目中打开tsconfig.json,将下面的代码添加到"strict": true, 下面: "strictNullChecks": false, 这样就能解决你的问题了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接