Merge pull request #27111 from backstage/blam/fixing-any-params

Fixing issue with `ParamKeys` type inferrence
This commit is contained in:
Ben Lambert
2024-10-15 09:12:34 +02:00
committed by GitHub
6 changed files with 45 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-plugin-api': patch
---
Fixing issue with types for `ParamKeys` leading to type mismatches across versions
+6 -2
View File
@@ -613,9 +613,13 @@ export type OptionalParams<
> = Params[keyof Params] extends never ? undefined : Params;
// @public @deprecated
export type ParamKeys<Params extends AnyParams> = keyof Params extends never
export type ParamKeys<Params extends AnyParams> = [AnyRouteRefParams] extends [
Params,
]
? string[]
: keyof Params extends never
? []
: (keyof Params)[];
: Array<keyof Params>;
// @public @deprecated
export type ParamNames<S extends string> =
@@ -87,7 +87,7 @@ describe('ExternalRouteRef', () => {
const _3 = createExternalRouteRef({ id: '3', params: ['x', 'y'] });
// @ts-expect-error
validateType<{ x: string }, any>(_3);
// extra z, we validate this at runtime instead
// @ts-expect-error
validateType<{ x: string; y: string; z: string }, any>(_3);
validateType<{ x: string; y: string }, false>(_3);
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { AnyParams, RouteRef } from './types';
import { AnyParams, RouteRef, ParamKeys } from './types';
import { createRouteRef } from './RouteRef';
describe('RouteRef', () => {
@@ -54,7 +54,7 @@ describe('RouteRef', () => {
validateType<undefined>(_2);
// @ts-expect-error
validateType<{ x: string; z: string }>(_2);
// extra z, we validate this at runtime instead
// @ts-expect-error
validateType<{ x: string; y: string; z: string }>(_2);
validateType<{ x: string; y: string }>(_2);
@@ -71,4 +71,28 @@ describe('RouteRef', () => {
// To avoid complains about missing expectations and unused vars
expect([_1, _2, _3, _4].join('')).toEqual(expect.any(String));
});
it('should properly infer param keys', () => {
function validateType<T>(_test: T) {}
validateType<ParamKeys<{ x: string; y: string }>>(['x', 'y']);
// @ts-expect-error
validateType<ParamKeys<{}>>(['foo']);
validateType<ParamKeys<{}>>([]);
// @ts-expect-error
validateType<ParamKeys<{ [key in string]: string }>>([1]);
validateType<ParamKeys<{ [key in string]: string }>>(['foo']);
// @ts-expect-error
validateType<ParamKeys<{ [key in string]: string } | undefined>>([1]);
validateType<ParamKeys<{ [key in string]: string } | undefined>>(['foo']);
// @ts-expect-error
validateType<ParamKeys<undefined>>(['foo']);
validateType<ParamKeys<undefined>>([]);
expect(true).toBeDefined();
});
});
@@ -102,7 +102,7 @@ describe('SubRouteRef', () => {
validateType<{ x: string; z: string }>(_2);
// @ts-expect-error
validateType<{ y: string }>(_2);
// extra z, we validate this at runtime instead
// @ts-expect-error
validateType<{ x: string; y: string; z: string }>(_2);
validateType<{ x: string; y: string }>(_2);
@@ -35,9 +35,13 @@ export type AnyParams = AnyRouteRefParams;
* @public
* @deprecated this type is deprecated and will be removed in the future
*/
export type ParamKeys<Params extends AnyParams> = keyof Params extends never
export type ParamKeys<Params extends AnyParams> = [AnyRouteRefParams] extends [
Params,
]
? string[]
: keyof Params extends never
? []
: (keyof Params)[];
: Array<keyof Params>;
/**
* Optional route params.