diff --git a/docs/overview/versioning-policy.md b/docs/overview/versioning-policy.md index fdb3a974b1..f34c74d55d 100644 --- a/docs/overview/versioning-policy.md +++ b/docs/overview/versioning-policy.md @@ -172,3 +172,13 @@ When we say _Supporting_ a Node.js release, that means the following: - The CI pipeline in the main Backstage repo tests towards the supported releases, and we encourage any other Backstage related projects to do the same. - New Backstage projects created with `@backstage/create-app` will have their `engines.node` version set accordingly. - Dropping compatibility with unsupported releases is not considered a breaking change. This includes using new syntax or APIs, as well as bumping dependencies that drop support for these versions. + +## TypeScript Releases + +The Backstage project uses [TypeScript](https://www.typescriptlang.org/) for type checking within the project, as well as external APIs and documentation. It is important to have a clear policy for which TypeScript versions we support, since we want to be able to adopt new TypeScript features, but at the same time not break existing projects that are using older versions. + +The TypeScript release cadence is roughly every three months. An important aspect of the TypeScript versioning is that it does not follow semver. In particular, there is no differentiation between major and minor versions, both of them are breaking. One way to think about it is to merge the two, for example version 4.7 can be considered major version 47, 5.0 is 50, and so on. Within these releases there can be a number of patch releases, which do follow semver. + +Our policy is to support the last 3 TypeScript versions, for example 4.8, 4.9, and 5.0. Converted to time, this means that we typically support the TypeScript version from the last six to nine months, depending on where in the TypeScript release window we are. This policy applies as a snapshot at the time of any given Backstage release, new TypeScript releases only apply to the following Backstage main-line release, not to the current one. + +For anyone maintaining their own Backstage project, this means that you should strive to bump to the latest TypeScript version at least every 6 months, or you may encounter breakages as you upgrade Backstage packages. If you encounter any issues in doing so, please [file an issue in the main Backstage repository](https://github.com/backstage/backstage/issues/new/choose), as per this policy we should always support the latest version. In order to ensure that we do not start using new TypeScript features too early, the Backstage project itself uses the version at the beginning of the currently supported window, in the above example that would be version 4.8. diff --git a/package.json b/package.json index 569257f73f..b70f83c5b9 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "semver": "^7.5.3", "shx": "^0.3.2", "ts-node": "^10.4.0", - "typescript": "~5.0.0" + "typescript": "~4.9.0" }, "prettier": "@spotify/prettier-config", "lint-staged": { diff --git a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx index 90cc928169..a09ea11b3d 100644 --- a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx +++ b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx @@ -95,8 +95,11 @@ export function TabbedCard(props: PropsWithChildren) { }); } else { React.Children.map(children, child => { - if (React.isValidElement(child) && child?.props.value === value) { - selectedTabContent = child?.props?.children; + if ( + React.isValidElement<{ children?: unknown; value?: unknown }>(child) && + child?.props.value === value + ) { + selectedTabContent = child?.props.children; } }); } diff --git a/plugins/catalog-backend/alpha-api-report.md b/plugins/catalog-backend/alpha-api-report.md index 8fd0eb571f..df3e809ade 100644 --- a/plugins/catalog-backend/alpha-api-report.md +++ b/plugins/catalog-backend/alpha-api-report.md @@ -79,7 +79,9 @@ export const catalogPlugin: () => BackendFeature; // @alpha export const createCatalogConditionalDecision: ( permission: ResourcePermission<'catalog-entity'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'catalog-entity', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @alpha diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index ea99d22fc5..2a9a79377b 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -75,14 +75,17 @@ export type ConditionTransformer = ( // @public export const createConditionAuthorizer: ( - rules: PermissionRule[], + rules: PermissionRule[], ) => (decision: PolicyDecision, resource: TResource | undefined) => boolean; // @public export const createConditionExports: < TResourceType extends string, TResource, - TRules extends Record>, + TRules extends Record< + string, + PermissionRule + >, >(options: { pluginId: string; resourceType: TResourceType; @@ -91,7 +94,9 @@ export const createConditionExports: < conditions: Conditions; createConditionalDecision: ( permission: ResourcePermission, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition + >, ) => ConditionalPolicyDecision; }; @@ -106,7 +111,7 @@ export const createConditionFactory: < // @public export const createConditionTransformer: < TQuery, - TRules extends PermissionRule[], + TRules extends PermissionRule[], >( permissionRules: [...TRules], ) => ConditionTransformer; diff --git a/plugins/playlist-backend/api-report.md b/plugins/playlist-backend/api-report.md index b755347205..6b51f316c4 100644 --- a/plugins/playlist-backend/api-report.md +++ b/plugins/playlist-backend/api-report.md @@ -15,6 +15,7 @@ import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PermissionPolicy } from '@backstage/plugin-permission-node'; import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { PlaylistMetadata } from '@backstage/plugin-playlist-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; @@ -25,7 +26,9 @@ import { ResourcePermission } from '@backstage/plugin-permission-common'; // @public (undocumented) export const createPlaylistConditionalDecision: ( permission: ResourcePermission<'playlist-list'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'playlist-list', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @public (undocumented) diff --git a/plugins/scaffolder-backend/alpha-api-report.md b/plugins/scaffolder-backend/alpha-api-report.md index 1fe1d4a6ed..363fcafd17 100644 --- a/plugins/scaffolder-backend/alpha-api-report.md +++ b/plugins/scaffolder-backend/alpha-api-report.md @@ -10,6 +10,7 @@ import { JsonObject } from '@backstage/types'; import { PermissionCondition } from '@backstage/plugin-permission-common'; import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { ResourcePermission } from '@backstage/plugin-permission-common'; import { TaskBroker } from '@backstage/plugin-scaffolder-backend'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; @@ -24,13 +25,17 @@ export const catalogModuleTemplateKind: () => BackendFeature; // @alpha (undocumented) export const createScaffolderActionConditionalDecision: ( permission: ResourcePermission<'scaffolder-action'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'scaffolder-action', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @alpha export const createScaffolderTemplateConditionalDecision: ( permission: ResourcePermission<'scaffolder-template'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'scaffolder-template', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @alpha diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 82610a2fc3..c618050810 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -326,7 +326,7 @@ export type TemplateParameterSchema = { // @public export const useCustomFieldExtensions: < - TComponentDataType = FieldExtensionOptions, + TComponentDataType = FieldExtensionOptions, >( outlet: React.ReactNode, ) => TComponentDataType[]; diff --git a/yarn.lock b/yarn.lock index c3de79ce29..3d40a46627 100644 --- a/yarn.lock +++ b/yarn.lock @@ -38096,7 +38096,7 @@ __metadata: semver: ^7.5.3 shx: ^0.3.2 ts-node: ^10.4.0 - typescript: ~5.0.0 + typescript: ~4.9.0 languageName: unknown linkType: soft @@ -41009,13 +41009,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:~5.0.0": - version: 5.0.4 - resolution: "typescript@npm:5.0.4" +"typescript@npm:~4.9.0": + version: 4.9.5 + resolution: "typescript@npm:4.9.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 82b94da3f4604a8946da585f7d6c3025fff8410779e5bde2855ab130d05e4fd08938b9e593b6ebed165bda6ad9292b230984f10952cf82f0a0ca07bbeaa08172 + checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db languageName: node linkType: hard @@ -41029,13 +41029,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@~5.0.0#~builtin": - version: 5.0.4 - resolution: "typescript@patch:typescript@npm%3A5.0.4#~builtin::version=5.0.4&hash=a1c5e5" +"typescript@patch:typescript@~4.9.0#~builtin": + version: 4.9.5 + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=a1c5e5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 6a1fe9a77bb9c5176ead919cc4a1499ee63e46b4e05bf667079f11bf3a8f7887f135aa72460a4c3b016e6e6bb65a822cb8689a6d86cbfe92d22cc9f501f09213 + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 languageName: node linkType: hard