Skip to content

Commit

Permalink
fix: downcast utility type (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
eegli authored Feb 27, 2024
1 parent d878fc8 commit a9bfe77
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/itchy-avocados-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@eegli/tinyparse": patch
---

Fix downcast utility type to default to `string[]`
4 changes: 2 additions & 2 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
AnyGlobal,
CommandArgPattern,
DefaultHandler,
Downcast,
DowncastFlag,
ErrorHandler,
FlagOptions,
FlagValue,
Expand Down Expand Up @@ -74,7 +74,7 @@ export class CommandBuilder<

// TODO: Figure out how to make this typecheck properly
return this as unknown as CommandBuilder<
Options & Record<K, Downcast<V>>,
Options & Record<K, DowncastFlag<V>>,
Globals
>;
}
Expand Down
32 changes: 14 additions & 18 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export type FlagValue = string | number | boolean | Date;
export type FlagOptions<V extends FlagValue = FlagValue> = {
longFlag: LongFlag;
shortFlag?: ShortFlag;
defaultValue: Downcast<V>;
defaultValue: DowncastFlag<V>;
required?: boolean;
description?: string;
};
Expand Down Expand Up @@ -63,8 +63,10 @@ export type Subcommand<Options, Globals, Args> = {
args: Args;
description?: string;
handler: Args extends string[]
? GenericHandler<Options, Globals, Downcast<Args>>
: GenericHandler<Options, Globals, string[]>;
? // Strict type annotation
GenericHandler<Options, Globals, DowncastArgs<Args>>
: // Loose type annotation
GenericHandler<Options, Globals, string[]>;
};

/**
Expand Down Expand Up @@ -149,20 +151,14 @@ type RemoveNever<T> = {
[K in keyof T as T[K] extends never ? never : K]: T[K];
};

export type Downcast<T> = T extends unknown[]
? {
[P in keyof T]: T[P] extends number
? number
: T[P] extends string
? string
: T[P] extends boolean
? boolean
: T[P];
}
export type DowncastArgs<T extends string[]> = {
[P in keyof T]: string;
};

export type DowncastFlag<T extends FlagValue> = T extends string
? string
: T extends number
? number
: T extends string
? string
: T extends boolean
? boolean
: T;
: T extends boolean
? boolean
: T;
12 changes: 12 additions & 0 deletions test/types/index.tst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe('subcommand option and global arguments', () => {
})
.setGlobals(() => ({
database: 'db',
fetch: () => {},
})).subcommand;

type HandlerParams = Parameters<
Expand All @@ -37,6 +38,12 @@ describe('subcommand option and global arguments', () => {
type HandlerGlobalParams = HandlerParams['globals'];

test('flags are inferred', () => {
expect<HandlerFlagParams>().type.toBeAssignable<{
foo: string;
bar: number;
baz: boolean;
qux: Date;
}>();
expect<HandlerFlagParams>().type.toMatch<{
foo: string;
bar: number;
Expand All @@ -45,8 +52,13 @@ describe('subcommand option and global arguments', () => {
}>();
});
test('globals are inferred', () => {
expect<HandlerGlobalParams>().type.toBeAssignable<{
database: string;
fetch: () => void;
}>();
expect<HandlerGlobalParams>().type.toMatch<{
database: string;
fetch: () => void;
}>();
});
});
Expand Down
15 changes: 15 additions & 0 deletions test/types/utils.tst.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, test } from 'tstyche';
import { DowncastArgs, DowncastFlag } from '../../src/types';

describe('type utils', () => {
test('downcast args', () => {
expect<DowncastArgs<string[]>>().type.toEqual<string[]>();
expect<DowncastArgs<['a', 'b']>>().type.toEqual<[string, string]>();
});
test('downcast flag', () => {
expect<DowncastFlag<1>>().type.toEqual<number>();
expect<DowncastFlag<'as'>>().type.toEqual<string>();
expect<DowncastFlag<true>>().type.toEqual<boolean>();
expect<DowncastFlag<Date>>().type.toEqual<Date>();
});
});

0 comments on commit a9bfe77

Please sign in to comment.