From 0060a382cbcf8340c094aa15dfb745895ac7e906 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Thu, 6 May 2021 17:02:56 -0600 Subject: [PATCH 1/2] Recommend `declare` instead of disabling `strictPropertyInitialization` Since TypeScript 3.7, which was released in November 2019, TypeScript supports declaring properties which will be initialized in a way that is invisible to TS via the `declare` property modifier. This enables using `strictPropertyInitialization` with class or field decorators (as well as other patterns which can initialize classes invisibly to TS). --- docs/_guide/decorators.md | 46 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/docs/_guide/decorators.md b/docs/_guide/decorators.md index 34e7c933..9c0b80b5 100644 --- a/docs/_guide/decorators.md +++ b/docs/_guide/decorators.md @@ -37,27 +37,31 @@ class HelloWorldElement extends HTMLElement { Class Field decorators get given the class and the field name so they can add custom functionality to the field. Because they operate on the fields, they must be put on top of or to the left of the field. -#### Disabling `strictPropertyInitialization` - -TypeScript comes with various "strict" mode settings, one of which is `strictPropertyInitialization` which TypeScript catch potential class properties which might not be assigned during construction of a class. This option conflicts with Catalyst's `@target`/`@targets` decorators, which safely do the assignment but TypeScript's simple heuristics cannot detect this. It's recommended to disable this option (other strict mode rules can still apply) in your `tsconfig.json` like so: - -```json -{ - "compilerOptions": { - "strict": true, - "strictPropertyInitialization": false - } -} -``` - -If you really want to keep the `strictPropertyInitialization` option set to `true`, another option would be to use TypeScript's [non-null assertion operator (`!`)](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator), adding this to each of your `@target`/`@targets` properties, like so: - -```typescript -class HelloWorldElement extends HTMLElement { - @target something!: HTMLElement - @targets items!: HTMLElement[] -} -``` +#### Supporting `strictPropertyInitialization` + +TypeScript comes with various "strict" mode settings, one of which is `strictPropertyInitialization` which TypeScript catch potential class properties which might not be assigned during construction of a class. This option conflicts with Catalyst's `@target`/`@targets` decorators, which safely do the assignment but TypeScript's simple heuristics cannot detect this. There are two ways to work around this: + +1. Use TypeScript's [`declare` modifier](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier) to tell TypeScript that the decorated field will still be set up correctly: + + ```typescript + class HelloWorldElement extends HTMLElement { + @target declare something: HTMLElement + @targets declare items: HTMLElement[] + } + ``` + + Note that this only works on TypeScript 3.7+, so if you're on an older version, you can also use the [definite initialization operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions) to do the same thing. + +2. You can also disable the compiler option (other strict mode rules can still apply) in your `tsconfig.json` like so: + + ```json + { + "compilerOptions": { + "strict": true, + "strictPropertyInitialization": false + } + } + ``` ### Method Decorators From d64e1cf279832c82877d7984db4613ca317f2fb9 Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Fri, 15 Oct 2021 09:46:15 -0600 Subject: [PATCH 2/2] Fix a typo --- docs/_guide/decorators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_guide/decorators.md b/docs/_guide/decorators.md index 9c0b80b5..806e30fa 100644 --- a/docs/_guide/decorators.md +++ b/docs/_guide/decorators.md @@ -39,7 +39,7 @@ Class Field decorators get given the class and the field name so they can add cu #### Supporting `strictPropertyInitialization` -TypeScript comes with various "strict" mode settings, one of which is `strictPropertyInitialization` which TypeScript catch potential class properties which might not be assigned during construction of a class. This option conflicts with Catalyst's `@target`/`@targets` decorators, which safely do the assignment but TypeScript's simple heuristics cannot detect this. There are two ways to work around this: +TypeScript comes with various "strict" mode settings, one of which is `strictPropertyInitialization` which lets TypeScript catch potential class properties which might not be assigned during construction of a class. This option conflicts with Catalyst's `@target`/`@targets` decorators, which safely do the assignment but TypeScript's simple heuristics cannot detect this. There are two ways to work around this: 1. Use TypeScript's [`declare` modifier](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier) to tell TypeScript that the decorated field will still be set up correctly: