Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript check for empty string

Is there a way for TypeScript to statically check for an empty string? Is there a way to statically require a non-empty string to be passed to a function?

let fn = function(a:string){  };  fn(''); 

or

let a = ''; fn(a); 

Can TS help us here?

like image 615
Alexander Mills Avatar asked Jun 22 '17 01:06

Alexander Mills


People also ask

How do I check if a string is empty?

Java String isEmpty() Method The isEmpty() method checks whether a string is empty or not. This method returns true if the string is empty (length() is 0), and false if not.

Is empty string falsey TypeScript?

Yes. All false , 0 , empty strings '' and "" , NaN , undefined , and null are always evaluated as false ; everything else is true .

Is empty in TypeScript?

To check if an object is empty in TypeScript: Use the Object. keys() method to get an array of the object's keys. Access the length property on the array. If the length property is equal to 0 , the object is empty.

How do you check if a string is not empty in JavaScript?

Use the length property to check if a string is empty, e.g. if (str. length === 0) {} . If the string's length is equal to 0 , then it's empty, otherwise it isn't empty.


2 Answers

I believe this is as close as you're going to get only using the typing system (rather than having a 'nonEmptyString' class)

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. } 

Testing it:

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

Unfortunately, you end up with warts since nonEmptyString is never. Which means you need to explicitly cast nonEmptyString back to 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) } 

One possible resolution is:

type nonEmptyString = string & { __nonEmptyStr: never }; 

Which alleviates the problem of having to explicitly cast back to a string (all three tests above are valid), but does pollute the type with __nonEmptyStr (which will be undefined if referenced).

like image 103
Rob Avatar answered Oct 03 '22 21:10

Rob


You can use this trick in your specific case:

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 
like image 45
Finesse Avatar answered Oct 03 '22 20:10

Finesse