From 3e05a2ee38559b848b487d3fae892b271dfb5908 Mon Sep 17 00:00:00 2001 From: Andrei Picus Date: Mon, 18 Nov 2019 08:08:23 +0100 Subject: [PATCH] Add type information for flags (#122) --- index.d.ts | 24 ++++++++++++----- index.test-d.ts | 72 ++++++++++++++++++++++++++----------------------- 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/index.d.ts b/index.d.ts index 67c50ff..8ee568d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -2,7 +2,7 @@ import {PackageJson} from 'type-fest'; import {Options as MinimistOptions} from 'minimist-options'; declare namespace meow { - interface Options { + interface Options { /** Define argument flags. @@ -23,7 +23,7 @@ declare namespace meow { } ``` */ - readonly flags?: MinimistOptions; + readonly flags?: Flags; /** Description to show above the help text. Default: The package.json `"description"` property. @@ -159,7 +159,17 @@ declare namespace meow { readonly hardRejection?: boolean; } - interface Result { + type TypedFlags = { + [F in keyof Flags]: Flags[F] extends {type: 'number'} + ? number + : Flags[F] extends {type: 'string'} + ? string + : Flags[F] extends {type: 'boolean'} + ? boolean + : unknown; + }; + + interface Result { /** Non-flag arguments. */ @@ -168,12 +178,12 @@ declare namespace meow { /** Flags converted to camelCase excluding aliases. */ - flags: {[name: string]: unknown}; + flags: TypedFlags & {[name: string]: unknown}; /** Flags converted camelCase including aliases. */ - unnormalizedFlags: {[name: string]: unknown}; + unnormalizedFlags: TypedFlags & {[name: string]: unknown}; /** The `package.json` object. @@ -236,7 +246,7 @@ const cli = meow(` foo(cli.input[0], cli.flags); ``` */ -declare function meow(helpMessage: string, options?: meow.Options): meow.Result; -declare function meow(options?: meow.Options): meow.Result; +declare function meow(helpMessage: string, options?: meow.Options): meow.Result; +declare function meow(options?: meow.Options): meow.Result; export = meow; diff --git a/index.test-d.ts b/index.test-d.ts index 419cf9f..a18615a 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,48 +1,52 @@ -import {expectType} from 'tsd'; +import {expectAssignable, expectType} from 'tsd'; import {PackageJson} from 'type-fest'; import meow = require('.'); import {Result} from '.'; -expectType(meow('Help text')); -expectType(meow('Help text', {hardRejection: false})); -expectType( - meow({ - flags: { - unicorn: { - type: 'boolean', - alias: 'u' - }, - fooBar: { - type: 'string', - default: 'foo' - } - } - }) +expectType>(meow('Help text')); +expectType>(meow('Help text', {hardRejection: false})); +expectAssignable<{flags: {foo: number}}>( + meow({flags: {foo: {type: 'number'}}}) ); -expectType(meow({description: 'foo'})); -expectType(meow({description: false})); -expectType(meow({help: 'foo'})); -expectType(meow({help: false})); -expectType(meow({version: 'foo'})); -expectType(meow({version: false})); -expectType(meow({autoHelp: false})); -expectType(meow({autoVersion: false})); -expectType(meow({pkg: {foo: 'bar'}})); -expectType(meow({argv: ['foo', 'bar']})); -expectType(meow({inferType: true})); -expectType(meow({booleanDefault: true})); -expectType(meow({booleanDefault: null})); -expectType(meow({booleanDefault: undefined})); -expectType(meow({hardRejection: false})); +expectAssignable<{flags: {foo: string}}>( + meow({flags: {foo: {type: 'string'}}}) +); +expectAssignable<{flags: {foo: boolean}}>( + meow({flags: {foo: {type: 'boolean'}}}) +); +expectType>(meow({description: 'foo'})); +expectType>(meow({description: false})); +expectType>(meow({help: 'foo'})); +expectType>(meow({help: false})); +expectType>(meow({version: 'foo'})); +expectType>(meow({version: false})); +expectType>(meow({autoHelp: false})); +expectType>(meow({autoVersion: false})); +expectType>(meow({pkg: {foo: 'bar'}})); +expectType>(meow({argv: ['foo', 'bar']})); +expectType>(meow({inferType: true})); +expectType>(meow({booleanDefault: true})); +expectType>(meow({booleanDefault: null})); +expectType>(meow({booleanDefault: undefined})); +expectType>(meow({hardRejection: false})); -const result = meow('Help text'); +const result = meow('Help text', { + flags: { + foo: {type: 'boolean', alias: 'f'}, + 'foo-bar': {type: 'number'} + }} +); expectType(result.input); -expectType<{[name: string]: unknown}>(result.flags); -expectType<{[name: string]: unknown}>(result.unnormalizedFlags); expectType(result.pkg); expectType(result.help); +expectType(result.flags.foo); +expectType(result.unnormalizedFlags.foo); +expectType(result.unnormalizedFlags.f); +expectType(result.unnormalizedFlags['foo-bar']); +expectType(result.flags.fooBar); + result.showHelp(); result.showHelp(1); result.showVersion();