Skip to content

Commit

Permalink
Refactor type mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
bakerkretzmar committed Dec 22, 2023
1 parent adfeac8 commit 36cdd32
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 21 deletions.
30 changes: 12 additions & 18 deletions src/js/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type RouteName = KnownRouteName | (string & {});
/**
* Information about a single route parameter.
*/
type ParameterInfo = { name: string; binding?: string };
type ParameterInfo = { name: string; optional: boolean; binding?: string };

/**
* A primitive route parameter value, as it would appear in a URL.
Expand Down Expand Up @@ -62,30 +62,24 @@ type HasQueryParam = { _query?: Record<string, unknown> };
type GenericRouteParamsObject = Record<keyof any, unknown> & HasQueryParam;
// `keyof any` essentially makes it function as a plain `Record`

/**
* Get only params for `optional: true` or `optional: false`.
*/
type GetParamsForOptionalSwitch<I extends readonly ParameterInfo[], TOptional extends boolean> = Extract<
I[number],
{ optional: TOptional }
>;

/**
* Map our parameter info to a routable object. We call twice to handle optional and non-optional params.
*/
type MapParamsToRoutable<I extends readonly ParameterInfo[]> =
{ [T in GetParamsForOptionalSwitch<I, true> as T['name']]?: Routable<T> } &
{ [T in GetParamsForOptionalSwitch<I, false> as T['name']]: Routable<T> }

/**
* An object of parameters for a specific named route.
*/
type KnownRouteParamsObject<I extends readonly ParameterInfo[], MappedParams = MapParamsToRoutable<I>> = {
[K in keyof MappedParams]: MappedParams[K]
type KnownRouteParamsObject<I extends readonly ParameterInfo[]> = {
[T in Extract<I[number], { optional: false }> as T['name']]: Routable<T>;
} & {
[T in Extract<I[number], { optional: true }> as T['name']]?: Routable<T>;
} & GenericRouteParamsObject;
// `readonly` allows TypeScript to determine the actual values of all the
// parameter names inside the array, instead of just seeing `string`.
// See https://github.com/tighten/ziggy/pull/664#discussion_r1329978447.

// Uncomment to test:
// type A = KnownRouteParamsObject<
// [{ name: 'foo'; optional: false }, { name: 'bar'; optional: true }]
// >;
// = { foo: ..., bar?: ... }

/**
* An object of route parameters.
*/
Expand Down
4 changes: 1 addition & 3 deletions tests/js/route.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assertType } from 'vitest';
import route, { RouteParams } from '../../src/js';
import route from '../../src/js';

// Add generated routes to use for testing inside this file. In a real app these declarations
// would be in a separate file generated by running `php artisan ziggy:generate --types`.
Expand All @@ -15,8 +15,6 @@ declare module '../../src/js' {
}
}

type T = RouteParams<'posts.comments.show'>;

// Test route name autocompletion by adding quotes inside `route()` - should suggest route names above
assertType(route());

Expand Down

0 comments on commit 36cdd32

Please sign in to comment.