Search code examples
typescripttypesassertargvassertion

Set the types of the args from `process.argv` in TypeScript, without type assertions


How can I, in TypeScript, set the types of the args passed in from process.argv, without using type assertions? Since using as would force the type, when I want to avoid that if possible.

What I have now:

type AppName = 'editor' | 'terminal';

function main(args: string[]): void {
  const app: AppName = args[0] as AppName;
}

main(process.argv.slice(2))

What I want (pseudo-code):

type AppName = 'editor' | 'terminal';

function main(args: string[]): void {
  // This doesn't actually work, since `in` doesn't work on `type`.
  if (!(args[0] in AppName)) {
    throw new Error("The first argument is not an app name.")
  }

  // The error: Type 'string' is not assignable to type 'AppName'.
  const app: AppName = args[0];
}

main(process.argv.slice(2))

Is anything similar to this possible? With the conditional, TS should detect that I have already ensured that the first arg is one of the given app names, and therefore accept setting it to a var with type AppName.


Solution

  • One way to do it would be to use type guard. Here's an article on medium about it

    I'm aware of that solution, but you may have something better available

    type AppName = 'editor' | 'terminal';
    
    function isAppName(toBeDetermined: any): toBeDetermined is AppName {
      if (toBeDetermined === 'editor' || toBeDetermined === 'terminal') {
        return true
      }
      return false
    } 
    
    function main(args: string[]): void {
      if (!isAppName(args[0])) {
        throw new Error("The first argument is not an app name.")
      }
    
      const app = args[0]; // const app: AppName
    }
    

    Here is a working playground for it