Home > Software design >  Why can't typescript recognise or type?
Why can't typescript recognise or type?

Time:04-13

I am using yargs to parse the command line parameters. Below is the code:

import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { ArgType } from './types';

const argv = yargs(hideBin(process.argv))
  .option('migrateName', {
    alias: 'n',
    description: 'migration name',
    type: 'string',
  })
  .demandOption('migrateName')
  .help()
  .alias('help', 'h').parse();

console.log(argv.migrateName)

I got a compile error:

Property 'migrateName' does not exist on type '{ [x: string]: unknown; migrateName: string; _: (string | number)[]; $0: string; } | Promise<{ [x: string]: unknown; migrateName: string; _: (string | number)[]; $0: string; }>'.
  Property 'migrateName' does not exist on type 'Promise<{ [x: string]: unknown; migrateName: string; _: (string | number)[]; $0: string; }>'

it says migrateName doesn't exist on argv. But when looking at the argv type, it has an or operator. It's type is:

{
    [x: string]: unknown;
    migrateName: string;
    _: (string | number)[];
    $0: string;
} | Promise<{
    [x: string]: unknown;
    migrateName: string;
    _: (string | number)[];
    $0: string;
}>

I don't understand why typescript complains about this type even it already has migrateName in its type.

The version I am using is:

"@types/yargs": "^17.0.10",
"yargs": "^17.4.1",
"typescript": "^4.6.3"

CodePudding user response:

TypeScript is actually describing the error, it's just a bit hard to read because there are some repeated types that have been expanded.

The entire error you have is this:

Property 'migrateName' does not exist on type '{ [x: string]: unknown; migrateName: string; _: (string | number)[]; $0: string; } | Promise<{ [x: string]: unknown; migrateName: string; _: (string | number)[]; $0: string; }>'.
  Property 'migrateName' does not exist on type 'Promise<{ [x: string]: unknown; migrateName: string; _: (string | number)[]; $0: string; }>'

If we look carefully, there are actually two lines to this error and a bunch of types that are repeated.

This type is repeated three times in the error message:

{ [x: string]: unknown; migrateName: string; _: (string | number)[]; $0: string; }

That looks like the CLI arguments you are trying to parse.

In our head, let's imagine that we have an alias for that type - let's call it Arguments.

If we use our imaginary Arguments type alias in that error message we get this:

Property 'migrateName' does not exist on type 'Arguments | Promise<Arguments>'.
  Property 'migrateName' does not exist on type 'Promise<Arguments>'

Now it's looking a bit clearer!

The yargs types say that the parse() function can return either the arguments themselves or a promise containing those arguments.

The TypeScript error is saying that you haven't handled all possible return types.
If a promise is returned then it won't have the migrateName property you are trying to access.

Solution

The simple fix is to use yargs's parseSync() function instead of parse().

  • Related