Understanding User-Defined Guard for Two Values in TypeScript

Asked 1 years ago, Updated 1 years ago, 444 views

When I tried to run the following code in TypeScriptPlayground,
testFunc(a);
However, there was a type error because a could be null.
In order to resolve this type error, I would like to write something like user-defined guard ais string on isValid, but I don't know how to write it.

If you know, please let me know.

If you assign a string instead of a string | null type, it will not happen, but
The code is not actually a fixed value, so the part where string|null allocates variables is
I want to leave it as it is.

Thank you for your cooperation.

constisValid=({a,b}:{a:string|null,b:string|null}):boolean=>{
  if(!a){
    return false;
  }
  if(!b){
    return false;
  }
  return true;
}

testFunc=(args:string)=>{
  console.log(args);
}

constmain=()=>{
  consta —string | null = null;
  const b:string | null = "B";

  if(isValid({a,b})){
    testFunc(a);
  } else{
    console.log("test");
  }

}
main();

typescript

2023-02-07 02:08

1 Answers

Answer the TypeScript version on the assumption that it is currently the latest version of v4.9.

First of all, the User-Defined Type Guard must have a Type predictor such that the return value type is foo is type.
Also, only one argument can be mentioned in the predicate, and the split algebra is unlikely to be used.
https://www.typescriptlang.org/docs/handbook/2/narrowing.html?#using-type-predicates

Then, when you use type predictor in an if statement, the most stringent content you can take in the code flow to that part of the scope is used.
In other words, no matter how many types you annotate, if you write consta:string | null=null;, the a type is null.
If you are writing a sample (although there are many ways to write it), it is recommended that you write it so that the value is not determined by the scope itself until the execution time.

Also, since {a,b} is only an abbreviation for {a:a,b:b}, the a property and the a variable of this object are different, the result of the type guard of the a property is unlikely to propagate to the a variable.

To sum up, if you want to keep the structure of the code presented, would it be as follows?

constisValid=(arg:any):arg is {a:string, b:string}=>{
  if(!arg.a){
    return false;
  }
  if(!arg.b){
    return false;
  }
  return true;
}

testFunc=(args:string)=>{
  console.log(args);
}

constmain=()=>{
  consta: string | null = ["A", null ] [Math.floor(Math.random()*2)];
  const b: string | null = ["B", null ] [Math.floor(Math.random()*2)];
  const tmp = {a,b};

  if(isValid(tmp)){
    testFunc(tmp.a);
  } else{
    console.log("test");
  }

}
main();

However, since it is difficult to write variables a, b, it is recommended that you write around the main function as follows:

const main=(a:string | null, b:string | null)=>{
  const tmp = {a,b};

  if(isValid(tmp)){
    testFunc(tmp.a);
  } else{
    console.log("test");
  }

}
main(null, "B");


2023-02-07 07:05

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.