fixes for TypeScript 5.0
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/core-plugin-api': patch
|
||||
'@backstage/plugin-scaffolder-react': patch
|
||||
'@backstage/plugin-scaffolder-node': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
Minor type tweaks for TypeScript 5.0
|
||||
@@ -15,12 +15,12 @@
|
||||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import inquirer from 'inquirer';
|
||||
import inquirer, { Answers } from 'inquirer';
|
||||
import { AnyFactory, Prompt } from './types';
|
||||
import * as factories from './factories';
|
||||
import partition from 'lodash/partition';
|
||||
|
||||
function applyPromptMessageTransforms<T>(
|
||||
function applyPromptMessageTransforms<T extends Answers>(
|
||||
prompt: Prompt<T>,
|
||||
transforms: {
|
||||
message: (msg: string) => string;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DistinctQuestion } from 'inquirer';
|
||||
import { Answers, DistinctQuestion } from 'inquirer';
|
||||
|
||||
export interface CreateContext {
|
||||
/** The package scope to use for new packages */
|
||||
@@ -37,7 +37,9 @@ export interface CreateContext {
|
||||
|
||||
export type AnyOptions = Record<string, string>;
|
||||
|
||||
export type Prompt<TOptions> = DistinctQuestion<TOptions> & { name: string };
|
||||
export type Prompt<TOptions extends Answers> = DistinctQuestion<TOptions> & {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export interface Factory<TOptions extends AnyOptions> {
|
||||
/**
|
||||
|
||||
@@ -376,7 +376,7 @@ export function Table<T extends object = {}>(props: TableProps<T>) {
|
||||
const newData = (data as any[]).filter(
|
||||
el =>
|
||||
!!Object.entries(selectedFilters)
|
||||
.filter(([, value]) => !!value.length)
|
||||
.filter(([, value]) => !!(value as { length?: number }).length)
|
||||
.every(([key, filterValue]) => {
|
||||
const fieldValue = extractValueByField(
|
||||
el,
|
||||
|
||||
@@ -91,11 +91,11 @@ export const AnalyticsContext = (options: {
|
||||
* @param values - Analytics context key/value pairs.
|
||||
* @internal
|
||||
*/
|
||||
export function withAnalyticsContext<P>(
|
||||
Component: React.ComponentType<P>,
|
||||
export function withAnalyticsContext<TProps extends {}>(
|
||||
Component: React.ComponentType<TProps>,
|
||||
values: AnalyticsContextValue,
|
||||
) {
|
||||
const ComponentWithAnalyticsContext = (props: P) => {
|
||||
const ComponentWithAnalyticsContext = (props: TProps) => {
|
||||
return (
|
||||
<AnalyticsContext attributes={values}>
|
||||
<Component {...props} />
|
||||
|
||||
@@ -58,11 +58,11 @@ export function useApi<T>(apiRef: ApiRef<T>): T {
|
||||
* @param apis - APIs for the context.
|
||||
* @public
|
||||
*/
|
||||
export function withApis<T>(apis: TypesToApiRefs<T>) {
|
||||
return function withApisWrapper<P extends T>(
|
||||
WrappedComponent: React.ComponentType<P>,
|
||||
export function withApis<T extends {}>(apis: TypesToApiRefs<T>) {
|
||||
return function withApisWrapper<TProps extends T>(
|
||||
WrappedComponent: React.ComponentType<TProps>,
|
||||
) {
|
||||
const Hoc = (props: PropsWithChildren<Omit<P, keyof T>>) => {
|
||||
const Hoc = (props: PropsWithChildren<Omit<TProps, keyof T>>) => {
|
||||
const apiHolder = useApiHolder();
|
||||
|
||||
const impls = {} as T;
|
||||
@@ -79,7 +79,7 @@ export function withApis<T>(apis: TypesToApiRefs<T>) {
|
||||
}
|
||||
}
|
||||
|
||||
return <WrappedComponent {...(props as P)} {...impls} />;
|
||||
return <WrappedComponent {...(props as TProps)} {...impls} />;
|
||||
};
|
||||
const displayName =
|
||||
WrappedComponent.displayName || WrappedComponent.name || 'Component';
|
||||
|
||||
@@ -101,7 +101,9 @@ export class MockStorageApi implements StorageApi {
|
||||
});
|
||||
}
|
||||
|
||||
observe$<T>(key: string): Observable<StorageValueSnapshot<T>> {
|
||||
observe$<T extends JsonValue>(
|
||||
key: string,
|
||||
): Observable<StorageValueSnapshot<T>> {
|
||||
return this.observable.filter(({ key: messageKey }) => messageKey === key);
|
||||
}
|
||||
|
||||
@@ -109,7 +111,7 @@ export class MockStorageApi implements StorageApi {
|
||||
return `${this.namespace}/${encodeURIComponent(key)}`;
|
||||
}
|
||||
|
||||
private notifyChanges<T>(message: StorageValueSnapshot<T>) {
|
||||
private notifyChanges<T extends JsonValue>(message: StorageValueSnapshot<T>) {
|
||||
for (const subscription of this.subscribers) {
|
||||
subscription.next(message);
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ export function wrapInTestApp(
|
||||
|
||||
let wrappedElement: React.ReactElement;
|
||||
if (Component instanceof Function) {
|
||||
wrappedElement = <Component />;
|
||||
wrappedElement = React.createElement(Component as ComponentType);
|
||||
} else {
|
||||
wrappedElement = Component as React.ReactElement;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ export async function renderInTestApp(
|
||||
): Promise<RenderResult> {
|
||||
let wrappedElement: React.ReactElement;
|
||||
if (Component instanceof Function) {
|
||||
wrappedElement = <Component />;
|
||||
wrappedElement = React.createElement(Component as ComponentType);
|
||||
} else {
|
||||
wrappedElement = Component as React.ReactElement;
|
||||
}
|
||||
|
||||
+2
-1
@@ -114,8 +114,9 @@ export function EntityAutocompletePicker<
|
||||
} as Partial<T>);
|
||||
}, [name, shouldAddFilter, selectedOptions, Filter, updateFilters]);
|
||||
|
||||
const filter = filters[name];
|
||||
if (
|
||||
(filters[name] && !('values' in filters[name])) ||
|
||||
(filter && typeof filter === 'object' && !('values' in filter)) ||
|
||||
!availableOptions.length
|
||||
) {
|
||||
return null;
|
||||
|
||||
@@ -57,11 +57,14 @@ export function FetchedEntityRefLinks<
|
||||
error,
|
||||
} = useAsync(async () => {
|
||||
const refs = entityRefs.reduce((acc, current) => {
|
||||
return 'metadata' in current ? acc : [...acc, parseEntityRef(current)];
|
||||
if (typeof current === 'object' && 'metadata' in current) {
|
||||
return acc;
|
||||
}
|
||||
return [...acc, parseEntityRef(current)];
|
||||
}, new Array<CompoundEntityRef>());
|
||||
|
||||
const pureEntities = entityRefs.filter(
|
||||
ref => 'metadata' in ref,
|
||||
ref => typeof ref === 'object' && 'metadata' in ref,
|
||||
) as Array<Entity>;
|
||||
|
||||
return refs.length > 0
|
||||
|
||||
@@ -161,8 +161,9 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(
|
||||
|
||||
const queryParams = Object.keys(requestedFilters).reduce(
|
||||
(params, key) => {
|
||||
const filter: EntityFilter | undefined =
|
||||
requestedFilters[key as keyof EntityFilters];
|
||||
const filter = requestedFilters[key as keyof EntityFilters] as
|
||||
| EntityFilter
|
||||
| undefined;
|
||||
if (filter?.toQueryValue) {
|
||||
params[key] = filter.toQueryValue();
|
||||
}
|
||||
|
||||
@@ -70,10 +70,14 @@ function countTriggersPerDay(builds: ReadonlyArray<Build>) {
|
||||
const values = Object.entries(days).map(([epoch, buildsThisDay]) => {
|
||||
const datapoint = Object.fromEntries(
|
||||
triggerReasons
|
||||
.map(reason => [
|
||||
reason,
|
||||
buildsThisDay.filter(build => build.triggeredBy === reason).length,
|
||||
])
|
||||
.map(
|
||||
reason =>
|
||||
[
|
||||
reason,
|
||||
buildsThisDay.filter(build => build.triggeredBy === reason)
|
||||
.length,
|
||||
] as const,
|
||||
)
|
||||
.filter(([_type, count]) => count > 0),
|
||||
) as Omit<TriggerReasonsDatapoint, '__epoch'>;
|
||||
|
||||
|
||||
+1
-1
@@ -134,7 +134,7 @@ export const StarredRatingButtons = (props: StarredRatingButtonsProps) => {
|
||||
return (
|
||||
<>
|
||||
{Object.values(FeedbackRatings)
|
||||
.filter(o => typeof o === 'number')
|
||||
.filter((o): o is number => typeof o === 'number')
|
||||
.map(starRating => (
|
||||
<IconButton
|
||||
key={starRating}
|
||||
|
||||
@@ -73,7 +73,7 @@ export const IssuesList = ({
|
||||
const filteredRepos = React.useMemo(
|
||||
() =>
|
||||
issuesByRepository && activeFilter.length
|
||||
? activeFilter.reduce(
|
||||
? activeFilter.reduce<IssuesByRepo>(
|
||||
(acc, val) => ({
|
||||
[val]: issuesByRepository[val],
|
||||
...acc,
|
||||
|
||||
@@ -172,8 +172,9 @@ export const PlaylistListProvider = <
|
||||
|
||||
const queryParams = Object.keys(requestedFilters).reduce(
|
||||
(params, key) => {
|
||||
const filter: PlaylistFilter | undefined =
|
||||
requestedFilters[key as keyof PlaylistFilters];
|
||||
const filter = requestedFilters[key as keyof PlaylistFilters] as
|
||||
| PlaylistFilter
|
||||
| undefined;
|
||||
if (filter?.toQueryValue) {
|
||||
params[key] = filter.toQueryValue();
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ export class RollbarApi {
|
||||
);
|
||||
}
|
||||
|
||||
private async get<T>(url: string, accessToken?: string) {
|
||||
private async get<T extends {}>(url: string, accessToken?: string) {
|
||||
const fullUrl = buildUrl(url);
|
||||
|
||||
if (this.logger) {
|
||||
@@ -119,7 +119,7 @@ export class RollbarApi {
|
||||
.then(json => camelcaseKeys<T>(json?.result, { deep: true }));
|
||||
}
|
||||
|
||||
private async getForProject<T>(
|
||||
private async getForProject<T extends {}>(
|
||||
url: string,
|
||||
projectName: string,
|
||||
useProjectToken = true,
|
||||
|
||||
@@ -120,7 +120,7 @@ describe('DefaultWorkflowRunner', () => {
|
||||
foo: z.number(),
|
||||
}),
|
||||
},
|
||||
}) as TemplateAction<unknown>,
|
||||
}) as TemplateAction,
|
||||
);
|
||||
|
||||
actionRegistry.register({
|
||||
|
||||
@@ -22,8 +22,8 @@ import { JsonObject } from '@backstage/types';
|
||||
|
||||
/** @public */
|
||||
export type TemplateActionOptions<
|
||||
TActionInput = {},
|
||||
TActionOutput = {},
|
||||
TActionInput extends JsonObject = {},
|
||||
TActionOutput extends JsonObject = {},
|
||||
TInputSchema extends Schema | z.ZodType = {},
|
||||
TOutputSchema extends Schema | z.ZodType = {},
|
||||
> = {
|
||||
@@ -48,10 +48,18 @@ export const createTemplateAction = <
|
||||
TOutputParams extends JsonObject = JsonObject,
|
||||
TInputSchema extends Schema | z.ZodType = {},
|
||||
TOutputSchema extends Schema | z.ZodType = {},
|
||||
TActionInput = TInputSchema extends z.ZodType<any, any, infer IReturn>
|
||||
TActionInput extends JsonObject = TInputSchema extends z.ZodType<
|
||||
any,
|
||||
any,
|
||||
infer IReturn
|
||||
>
|
||||
? IReturn
|
||||
: TInputParams,
|
||||
TActionOutput = TOutputSchema extends z.ZodType<any, any, infer IReturn>
|
||||
TActionOutput extends JsonObject = TOutputSchema extends z.ZodType<
|
||||
any,
|
||||
any,
|
||||
infer IReturn
|
||||
>
|
||||
? IReturn
|
||||
: TOutputParams,
|
||||
>(
|
||||
|
||||
@@ -75,8 +75,8 @@ export type ActionContext<
|
||||
|
||||
/** @public */
|
||||
export type TemplateAction<
|
||||
TActionInput = unknown,
|
||||
TActionOutput = JsonObject,
|
||||
TActionInput extends JsonObject = JsonObject,
|
||||
TActionOutput extends JsonObject = JsonObject,
|
||||
> = {
|
||||
id: string;
|
||||
description?: string;
|
||||
|
||||
@@ -64,7 +64,7 @@ export type FieldExtensionOptions<
|
||||
*/
|
||||
export interface FieldExtensionComponentProps<
|
||||
TFieldReturnValue,
|
||||
TUiOptions extends {} = {},
|
||||
TUiOptions = unknown,
|
||||
> extends FieldProps<TFieldReturnValue> {
|
||||
uiSchema: FieldProps['uiSchema'] & {
|
||||
'ui:options'?: TUiOptions;
|
||||
|
||||
@@ -66,9 +66,6 @@ createDevApp()
|
||||
<EntityGridItem xs={12} md={6} entity={entity('passed')}>
|
||||
<EntitySonarQubeCard />
|
||||
</EntityGridItem>
|
||||
<EntityGridItem xs={12} entity={entity(undefined)}>
|
||||
<EntitySonarQubeCard />
|
||||
</EntityGridItem>
|
||||
</Grid>
|
||||
</Content>
|
||||
</Page>
|
||||
@@ -79,7 +76,7 @@ createDevApp()
|
||||
deps: {},
|
||||
factory: () =>
|
||||
({
|
||||
getFindingSummary: async componentKey => {
|
||||
getFindingSummary: async ({ componentKey }) => {
|
||||
switch (componentKey) {
|
||||
case 'error':
|
||||
throw new Error('Error!');
|
||||
|
||||
@@ -59,7 +59,7 @@ export const Content = (props: StackOverflowQuestionsContentProps) => {
|
||||
return <Typography paragraph>could not load questions</Typography>;
|
||||
}
|
||||
|
||||
const getSecondaryText = (answer_count: Number) =>
|
||||
const getSecondaryText = (answer_count: number) =>
|
||||
answer_count > 1 ? `${answer_count} answers` : `${answer_count} answer`;
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user