From b71d0c8495e8b3e9bd9e5c68328cd19f43d7760f Mon Sep 17 00:00:00 2001 From: Victor <106590915+victor-diez-sonarsource@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:45:31 +0200 Subject: [PATCH] Modify rule S4782: Adapt to LaYC (#2681) Co-authored-by: Yassin Kammoun <52890329+yassin-kammoun-sonarsource@users.noreply.github.com> --- rules/S4782/javascript/rule.adoc | 84 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/rules/S4782/javascript/rule.adoc b/rules/S4782/javascript/rule.adoc index 12200bcd75..ecbe26ffb9 100644 --- a/rules/S4782/javascript/rule.adoc +++ b/rules/S4782/javascript/rule.adoc @@ -1,56 +1,58 @@ == Why is this an issue? -In TypeScript there are several ways to declare a property with ``++undefined++`` value: adding ``++| undefined++`` in the property type or using optional property syntax (``++?++`` after its name). Use ``++| undefined++`` syntax when you want to be explicit that an object has that property, in that case TypeScript compiler will not allow omitting it: +In TypeScript, there are two ways to define properties or parameters that are potentially ``++undefined++``: ----- -interface Person { - name: string; - address: string | undefined; -} - -let John = { name: "John" }; // will not compile -let John = { name: "John", address: undefined }; // will compile, we want to be explicit when person does not have home ----- - -Use optional property syntax for properties holding some additional information. - ----- -interface Person { - name: string; - pet?: string; -} - -let John = { name: "John" }; // will compile -let John = { name: "John", pet: undefined }; // will compile, there is no pet like for the object on previous line -let John = { name: "John", pet: "Benji" }; // will compile ----- - -Using ``++| undefined++`` for optional property is redundant, it can be omitted without change to the actual type. Still if you want to force the property in the object consider using only ``++| undefined++`` without ``++?++``. - - -=== Noncompliant code example - -[source,javascript] ----- -interface Person { - name: string; - address? : string | undefined; // Noncompliant, "?" should be removed - pet?: Animal | undefined; // Noncompliant, "undefined" should be removed -} ----- - - -=== Compliant solution +* Union with `undefined`: Adding ``++| undefined++`` in the property type makes the property __required__, but can be `undefined`. Use this syntax when you want to be explicit that an object should provide that property, in which case the TypeScript compiler will not allow omitting it. [source,javascript] ---- interface Person { name: string; address: string | undefined; - pet?: Animal; +} + +let John = { name: "John", address: undefined }; +---- + +* Optional property syntax (``++?++`` after its name): The property is __optional__, which means that an object can omit it and let the TypeScript compiler provide it as being `undefined`. + +[source,javascript] +---- +interface Person { + name: string; + address?: string; +} + +let John = { name: "John" }; +---- + +This rule checks for optional property declarations that use both the `?` syntax and unions with `undefined`. + +[source,javascript,diff-id=1,diff-type=noncompliant] +---- +interface Person { + name: string; + address?: string | undefined; // Noncompliant: using both syntaxes is redundant } ---- +Choose one of the syntaxes to declare optional properties and remove the other one. Consider using only ``++| undefined++`` if you want to make the property explicit in the object. + +[source,javascript,diff-id=1,diff-type=compliant] +---- +interface Person { + name: string; + address?: string; +} +---- + +== Resources + +=== Documentation + +* https://www.typescriptlang.org/docs/handbook/2/objects.html#optional-properties[TypeScript - Optional Properties] +* https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types[TypeScript - Union Types] + ifdef::env-github,rspecator-view[] '''