diff --git a/linter-4.2/.gitignore b/linter-4.2/.gitignore index 3ded455fc811af5ac325bb4ed532facefecd86a4..4797db793b998b8c2ea246115378791d451072f7 100644 --- a/linter-4.2/.gitignore +++ b/linter-4.2/.gitignore @@ -2,6 +2,7 @@ build dist bundle node_modules +cookbook_convertor/md *.tsbuildinfo .vs .vscode diff --git a/linter-4.2/docs/rules/recipe1.md b/linter-4.2/docs/rules/recipe1.md index 317d04c6bd75c5d7c80e2e19a7553595833174ac..cda73e56f251fa409b819241734af7ca03fc3039 100644 --- a/linter-4.2/docs/rules/recipe1.md +++ b/linter-4.2/docs/rules/recipe1.md @@ -27,7 +27,7 @@ data by numeric indices. ``` class X { - public name: number + public name: number = 0 } let x = {name: 1} console.log(x.name) diff --git a/linter-4.2/docs/rules/recipe115.md b/linter-4.2/docs/rules/recipe115.md deleted file mode 100644 index ee73f68fd25bfc22657de9f15ea50dd826f62462..0000000000000000000000000000000000000000 --- a/linter-4.2/docs/rules/recipe115.md +++ /dev/null @@ -1,21 +0,0 @@ -# Scripts and modules - -Rule ``arkts-no-scripts`` - -**Severity: error** - -In general, scripts and modules in ArkTS are very close to TypeScript. -Differences are described in separate recipes. - - -## See also - -- Recipe 118: Special import type declarations are not supported (``arkts-no-special-imports``) -- Recipe 119: Importing a module for side-effects only is not supported (``arkts-no-side-effects-imports``) -- Recipe 120: ``import default as ...`` is not supported (``arkts-no-import-default-as``) -- Recipe 121: ``require`` and ``import`` assignment are not supported (``arkts-no-require``) -- Recipe 124: Export list declaration is not supported (``arkts-no-export-list-decl``) -- Recipe 125: Re-exporting is supported with restrictions (``arkts-limited-reexport``) -- Recipe 126: ``export = ...`` assignment is not supported (``arkts-no-export-assignment``) - - diff --git a/linter-4.2/docs/rules/recipe118.md b/linter-4.2/docs/rules/recipe118.md index 0041552fdb013d8acf3a5c3078f2ebc668725250..f625bc3e982353617c9dd28f7c6d67ff886e1e6d 100644 --- a/linter-4.2/docs/rules/recipe118.md +++ b/linter-4.2/docs/rules/recipe118.md @@ -14,10 +14,10 @@ Use ordinary import instead. ``` // Re-using the same import - import { APIResponseType } from "./api" + import { APIResponseType } from "api" // Explicitly use import type - import type { APIResponseType } from "./api" + import type { APIResponseType } from "api" ``` @@ -26,7 +26,7 @@ Use ordinary import instead. ``` - import { APIResponseType } from "./api" + import { APIResponseType } from "api" ``` diff --git a/linter-4.2/docs/rules/recipe123.md b/linter-4.2/docs/rules/recipe123.md deleted file mode 100644 index 93667373868f3ab91ac6ca468f8d5bd25ec90c65..0000000000000000000000000000000000000000 --- a/linter-4.2/docs/rules/recipe123.md +++ /dev/null @@ -1,61 +0,0 @@ -# Renaming in export declarations is not supported - -Rule ``arkts-no-export-renaming`` - -**Severity: error** - -ArkTS does not support renaming in export declarations. Similar effect -can be achieved through setting an alias for the exported entity. - - -## TypeScript - - -``` - - // file1.ts - class MyClass { - // ... - } - - export { MyClass as RenamedClass } - - // file2.ts - import { RenamedClass } from "./file1" - - function main(): void { - const myObject = new RenamedClass() - // ... - } - -``` - -## ArkTS - - -``` - - // module1 - class MyClass { - // ... - } - - export type RenamedClass = MyClass - - // module2 - import { RenamedClass } from "./module1" - - function main(): void { - const myObject = new RenamedClass() - // ... - } - -``` - -## See also - -- Recipe 124: Export list declaration is not supported (``arkts-no-export-list-decl``) -- Recipe 125: Re-exporting is not supported (``arkts-no-reexport``) -- Recipe 126: ``export = ...`` assignment is not supported (``arkts-no-export-assignment``) - - diff --git a/linter-4.2/docs/rules/recipe128.md b/linter-4.2/docs/rules/recipe128.md index 9a5ccebd49091bd5476bf510ae314d8579f3c80d..ddba6753b7c5499be4977aeec2bc5810c359c4f4 100644 --- a/linter-4.2/docs/rules/recipe128.md +++ b/linter-4.2/docs/rules/recipe128.md @@ -25,7 +25,7 @@ own mechanisms for interoperating with JavaScript. ``` // Import what you need from the original module - import { normalize } from "../someModule" + import { normalize } from "someModule" ``` diff --git a/linter-4.2/docs/rules/recipe130.md b/linter-4.2/docs/rules/recipe130.md index da2aada018a1563dd2c1f404b017a3434b285fa7..4a5c602e60d71e12f414a52a30e3741afa26b6a7 100644 --- a/linter-4.2/docs/rules/recipe130.md +++ b/linter-4.2/docs/rules/recipe130.md @@ -35,7 +35,7 @@ import is a compile-time, not a runtime feature. Use ordinary syntax for } // in program - import { mathLib } from "./math-lib" + import { mathLib } from "math-lib" mathLib.isPrime(2) ``` diff --git a/linter-4.2/docs/rules/recipe131.md b/linter-4.2/docs/rules/recipe131.md index c9f6e9c22c3de7ef824bd6054afee845478aceed..a103967cd268676efdca9c305a6a8285ef13c622 100644 --- a/linter-4.2/docs/rules/recipe131.md +++ b/linter-4.2/docs/rules/recipe131.md @@ -13,7 +13,7 @@ has its own mechanisms for interoperating with JavaScript. ``` - import { something } from "./module.js" + import { something } from "module.js" ``` @@ -22,7 +22,7 @@ has its own mechanisms for interoperating with JavaScript. ``` - import { something } from "./module" + import { something } from "module" ``` diff --git a/linter-4.2/docs/rules/recipe133.md b/linter-4.2/docs/rules/recipe133.md index 222bfdee09033650658d89ce1087c5782bead853..ab2f0a51e351586caadd1801f03aa0fedc8d5fdb 100644 --- a/linter-4.2/docs/rules/recipe133.md +++ b/linter-4.2/docs/rules/recipe133.md @@ -14,7 +14,7 @@ import syntax instead. ``` - const zipUtil = await import("./utils/create-zip-file") + const zipUtil = await import("utils/create-zip-file") ``` @@ -23,7 +23,7 @@ import syntax instead. ``` - import { zipUtil } from "./utils/create-zip-file" + import { zipUtil } from "utils/create-zip-file" ``` diff --git a/linter-4.2/docs/rules/recipe135.md b/linter-4.2/docs/rules/recipe135.md index 545a49b9b8351cd67693e04219743eea6bbb4f07..5e7bb88359c03032d55eb6606419f5a5c08d9f22 100644 --- a/linter-4.2/docs/rules/recipe135.md +++ b/linter-4.2/docs/rules/recipe135.md @@ -15,9 +15,10 @@ namespaces instead. ``` var C = (function() { - function C(n) { - this.p = n + function C(n: number) { + this.p = n // Compile-time error only with noImplicitThis } + C.staticProperty = 0 return C })() C.staticProperty = 1 diff --git a/linter-4.2/docs/rules/recipe136.md b/linter-4.2/docs/rules/recipe136.md index eb2ada7062458b5bd9243fad473283a77161429c..550b95b54e40f1f03f13f26b9b4e52e9909d9add 100644 --- a/linter-4.2/docs/rules/recipe136.md +++ b/linter-4.2/docs/rules/recipe136.md @@ -15,7 +15,7 @@ applicable to the static typing. ``` var C = function(p) { - this.p = p + this.p = p // Compile-time error only with noImplicitThis } C.prototype = { diff --git a/linter-4.2/docs/rules/recipe137.md b/linter-4.2/docs/rules/recipe137.md index 588cc70f46e523414ec8c99dc61aad374f963c14..5cb8d691d69879fb83eece870004ac011d61267b 100644 --- a/linter-4.2/docs/rules/recipe137.md +++ b/linter-4.2/docs/rules/recipe137.md @@ -30,7 +30,7 @@ objects with dynamically changed layout are not supported. export let abc : number = 0 // file2 - import * as M from "../file1" + import * as M from "file1" M.abc = 200 diff --git a/linter-4.2/docs/rules/recipe138.md b/linter-4.2/docs/rules/recipe138.md index f97ec50ae8cf49b9c6d2ed321ed69e7603f3f779..7dfec46f8cc36c700f907fd31e80ff46563bcaaf 100644 --- a/linter-4.2/docs/rules/recipe138.md +++ b/linter-4.2/docs/rules/recipe138.md @@ -8,6 +8,9 @@ Currently ArkTS does not support utility types from TypeScript extensions to the standard library (``Omit``, ``Pick``, etc.). Exceptions are: ``Partial``, ``Record``. +For ``Record`` type, the type of value must be either optional or unioned with +the ``undefined`` type. + ## TypeScript @@ -22,6 +25,21 @@ standard library (``Omit``, ``Pick``, etc.). Exceptions are: ``Partial``, type QuantumPerson = Omit + let persons : Record = { + "Alice": { + name: "Alice", + age: 32, + location: "Shanghai" + }, + "Bob": { + name: "Bob", + age: 48, + location: "New York" + } + } + console.log(persons["Bob"].age) + console.log(persons["Rob"].age) // Runtime exception + ``` ## ArkTS @@ -30,14 +48,34 @@ standard library (``Omit``, ``Pick``, etc.). Exceptions are: ``Partial``, ``` class Person { - name: string - age: number - location: string + name: string = "" + age: number = 0 + location: string = "" } class QuantumPerson { - name: string - age: number + name: string = "" + age: number = 0 + } + + type OptionalPerson = Person | undefined + let persons : Record = { + // Or: + // let persons : Record = { + "Alice": { + name: "Alice", + age: 32, + location: "Shanghai" + }, + "Bob": { + name: "Bob", + age: 48, + location: "New York" + } + } + console.log(persons["Bob"]!.age) + if (persons["Rob"]) { // Explicit value check, no runtime exception + console.log(persons["Rob"].age) } ``` diff --git a/linter-4.2/docs/rules/recipe139.md b/linter-4.2/docs/rules/recipe139.md index 5b27d1ebfa1009bd3986a339da8172aec5b19fef..70fd6896612202816c9229291c7c470d499e8e00 100644 --- a/linter-4.2/docs/rules/recipe139.md +++ b/linter-4.2/docs/rules/recipe139.md @@ -49,15 +49,17 @@ this rule and their layout cannot be changed in runtime. // ... } - function readImage( + async function readImage( path: string, callback: (err: Error, image: MyImage) => void ) : Promise { - // async implementation + // In real world, the implementation is more complex, + // involving real network / DB logic, etc. + return await new MyImage() } function readImageSync(path: string) : MyImage { - // sync implementation + return new MyImage() } ``` diff --git a/linter-4.2/docs/rules/recipe142.md b/linter-4.2/docs/rules/recipe142.md index cca78dc76637bdb0eda7fa5750cb6a3bc51bc497..7cef054e7cba81bc32feedebfb1e795d46ccd299 100644 --- a/linter-4.2/docs/rules/recipe142.md +++ b/linter-4.2/docs/rules/recipe142.md @@ -37,7 +37,7 @@ does not support literal types. let y : number[] = [10, 20] class Label { - text : string + text : string = "" } // Type 'Label': diff --git a/linter-4.2/docs/rules/recipe143.md b/linter-4.2/docs/rules/recipe143.md index 946b66efabc033db1d1035ab972de036f8cd2872..9dbec44af7a89f9264e0d8d8b0957a770ff3f0ae 100644 --- a/linter-4.2/docs/rules/recipe143.md +++ b/linter-4.2/docs/rules/recipe143.md @@ -15,7 +15,7 @@ in runtime does not make sense for the statically typed language. Use ordinary ``` - import { obj } from "./something.json" assert { type: "json" } + import { obj } from "something.json" assert { type: "json" } ``` @@ -25,7 +25,7 @@ in runtime does not make sense for the statically typed language. Use ordinary ``` // Correctness of importing T will be checked in compile-time: - import { something } from "./module" + import { something } from "module" ``` diff --git a/linter-4.2/docs/rules/recipe145.md b/linter-4.2/docs/rules/recipe145.md index 37e7be51f165a952926ccaf4efa3e2876798a817..022f436ff45b81710ec06c255bae2363dc600dcd 100644 --- a/linter-4.2/docs/rules/recipe145.md +++ b/linter-4.2/docs/rules/recipe145.md @@ -16,15 +16,21 @@ following flags should be turned on: ``noImplicitReturns``, ``` class C { - n: number - s: string + n: number // Compile-time error only with strictPropertyInitialization + s: string // Compile-time error only with strictPropertyInitialization } + // Compile-time error only with noImplicitReturns function foo(s: string): string { - console.log(s) + if (s != "") { + console.log(s) + return s + } else { + console.log(s) + } } - let n: number = null + let n: number = null // Compile-time error only with strictNullChecks ``` @@ -50,7 +56,7 @@ following flags should be turned on: ``noImplicitReturns``, ## See also -- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-undefined-unknown``) +- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-unknown``) - Recipe 146: Switching off type checks with in-place comments is not allowed (``arkts-strict-typing-required``) diff --git a/linter-4.2/docs/rules/recipe146.md b/linter-4.2/docs/rules/recipe146.md index f00a66b1563b5c3d4fac8f031a578988df342655..6426faf2820b61e31a2fde93e7bdaba0d591392c 100644 --- a/linter-4.2/docs/rules/recipe146.md +++ b/linter-4.2/docs/rules/recipe146.md @@ -20,9 +20,10 @@ with special comments is not allowed. In particular, ``@ts-ignore`` and // Some code with switched off type checker // ... - // @ts-ignore let s1: string = null // No error, type checker suppressed - let s2: string = null // Compile-time error + + // @ts-ignore + let s2: string = null // No error, type checker suppressed ``` @@ -38,7 +39,7 @@ with special comments is not allowed. In particular, ``@ts-ignore`` and ## See also -- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-undefined-unknown``) +- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-unknown``) - Recipe 145: Strict type checking is enforced (``arkts-strict-typing``) diff --git a/linter-4.2/docs/rules/recipe147.md b/linter-4.2/docs/rules/recipe147.md index 6a81f41c8e315e4530e5fe285ca02d2cbbf24414..de1f456d1eb55e88aed93e13045a3157ed1b05fe 100644 --- a/linter-4.2/docs/rules/recipe147.md +++ b/linter-4.2/docs/rules/recipe147.md @@ -24,4 +24,3 @@ through importing ArkTS code base. Imports in reverse direction are supported. ``` - diff --git a/linter-4.2/docs/rules/recipe17.md b/linter-4.2/docs/rules/recipe17.md index 4dd591c0eb9e6cf06a34a85862ae84f7057d2a83..93066f260be9ab7a3d18f5975b00278abd6fb723 100644 --- a/linter-4.2/docs/rules/recipe17.md +++ b/linter-4.2/docs/rules/recipe17.md @@ -32,7 +32,7 @@ ArkTS does not allow indexed signatures, use arrays instead. ``` class X { - public f: string[] + public f: string[] = [] } let myArray: X = new X() diff --git a/linter-4.2/docs/rules/recipe2.md b/linter-4.2/docs/rules/recipe2.md index 623cbff522305e062b19fe33f58679239e9afd37..04a96f96710df337f784ec458939864ec04f927b 100644 --- a/linter-4.2/docs/rules/recipe2.md +++ b/linter-4.2/docs/rules/recipe2.md @@ -29,7 +29,7 @@ and cannot be changed at runtime. ``` class SomeClass { - public someProperty : string + public someProperty : string = "" } let o = new SomeClass() diff --git a/linter-4.2/docs/rules/recipe24.md b/linter-4.2/docs/rules/recipe24.md deleted file mode 100644 index 174d840558bf5fa39a0a3acc06f8c5fb2455995c..0000000000000000000000000000000000000000 --- a/linter-4.2/docs/rules/recipe24.md +++ /dev/null @@ -1,46 +0,0 @@ -# Optional parameters are not supported for primitive types - -Rule ``arkts-no-opt-params`` - -**Severity: error** - -ArkTS does not support optional parameters of primitive types. -You can use default parameter values or reference types. For reference types, -non-specified optional parameter is set to ``null``. - - -## TypeScript - - -``` - - // x is an optional parameter: - function f(x?: number) { - console.log(x) // log undefined or number - } - - // x is a required parameter with the default value: - function g(x: number = 1) { - console.log(x) - } - -``` - -## ArkTS - - -``` - - // You can use reference type (will be set to null if missing): - function f(x?: Number) { - console.log(x) // log null or some number - } - - // You can use a required parameter with the default value: - function g(x: number = 1) { - console.log(x) - } - -``` - - diff --git a/linter-4.2/docs/rules/recipe33.md b/linter-4.2/docs/rules/recipe33.md deleted file mode 100644 index 4b8adbb0738364eac0d715f7718df1f6d3858cb4..0000000000000000000000000000000000000000 --- a/linter-4.2/docs/rules/recipe33.md +++ /dev/null @@ -1,58 +0,0 @@ -# Optional properties are not supported for primitive types - -Rule ``arkts-no-opt-props`` - -**Severity: error** - -ArkTS does not support optional properties of primitive types. You can use -properties with default values or reference types. For reference types, -non-specified optional property is set to ``null``. This rule applies both to -classes and interfaces. - - -## TypeScript - - -``` - - class CompilerOptions { - strict?: boolean - sourcePath?: string - targetPath?: string - } - - let options: CompilerOptions = { - strict: true, - sourcePath: "./src" - } - - if (options.targetPath == undefined) { - // Some logic - } - -``` - -## ArkTS - - -``` - - class CompilerOptions { - strict: boolean = false - sourcePath: string = "" - targetPath?: string - } - - let options: CompilerOptions = { - strict: true, - sourcePath: "./src" - // targetPath is implicitly set to null - } - - if (options.targetPath == null) { - // Some logic - } - -``` - - diff --git a/linter-4.2/docs/rules/recipe40.md b/linter-4.2/docs/rules/recipe40.md index 9fd22580fbf472bf9bebc48b03bca25c45d5cced..dd4221b1457b466a4de5876eb63a5733c817c18d 100644 --- a/linter-4.2/docs/rules/recipe40.md +++ b/linter-4.2/docs/rules/recipe40.md @@ -28,8 +28,8 @@ types in place. Declare classes and interfaces explicitly instead. ``` class O { - x: number - y: number + x: number = 0 + y: number = 0 } let o: O = {x: 2, y: 3} diff --git a/linter-4.2/docs/rules/recipe45.md b/linter-4.2/docs/rules/recipe45.md index 20680c932cca974c8ba607d0e640b81b7697af7b..70f14066e4d58cd71b81e1178978f4aa176cdbb5 100644 --- a/linter-4.2/docs/rules/recipe45.md +++ b/linter-4.2/docs/rules/recipe45.md @@ -13,7 +13,8 @@ to be explicitly specified. ``` - let f = (s) => { // type any is assumed + // Compile-time error only with noImplicitAny: + let f = (s /* type any is assumed */) => { console.log(s) } diff --git a/linter-4.2/docs/rules/recipe51.md b/linter-4.2/docs/rules/recipe51.md index 9b6ddc1fd820b6ee7dab6b681e90068ae0c04bbf..700a2409c4924fa197aee56960e8de244a85f5d7 100644 --- a/linter-4.2/docs/rules/recipe51.md +++ b/linter-4.2/docs/rules/recipe51.md @@ -29,7 +29,7 @@ may be specified. ``` interface C { - foo() + foo(): void } class C1 implements C { diff --git a/linter-4.2/docs/rules/recipe52.md b/linter-4.2/docs/rules/recipe52.md index 91042ae7740cc4270ead455db209cd7b71fe9219..f4ff3fd4b324df772894a9034fb7c0d41370f369 100644 --- a/linter-4.2/docs/rules/recipe52.md +++ b/linter-4.2/docs/rules/recipe52.md @@ -19,7 +19,7 @@ existence during compilation. let n = person["name"] let e = person["isEmployee"] - let s = person["office"] // undefined + let s = person["office"] // Compile-time error only with noImplicitAny ``` diff --git a/linter-4.2/docs/rules/recipe53.md b/linter-4.2/docs/rules/recipe53.md index 17c22a056818e171f8dee46ffb6123ba01f2ebd6..ea6c5a8a17992770b01f502dc657cad202b39303 100644 --- a/linter-4.2/docs/rules/recipe53.md +++ b/linter-4.2/docs/rules/recipe53.md @@ -8,6 +8,10 @@ ArkTS supports ``as`` keyword as the only syntax for type casts. Incorrect cast causes a compile-time error or runtime ``ClassCastException``. ```` syntax for type casts is not supported. +However, if a **primitive** type (e.g. a ``number`` or a ``boolean``) must be +cast to the reference type, this must be done through the ``new ...`` expression +instead of ``as``. + ## TypeScript @@ -31,6 +35,14 @@ Incorrect cast causes a compile-time error or runtime ``ClassCastException``. let c3 = createShape() as Square console.log(c3.y) // undefined + // Important corner case for casting primitives to the boxed counterparts: + // The left operand is not properly boxed here in in runtime + // because "as" has no runtime effect in TypeScript + let e1 = (5.0 as Number) instanceof Number // false + + // Number object is created and instanceof works as expected: + let e2 = (new Number(5.0)) instanceof Number // true + ``` ## ArkTS @@ -51,6 +63,9 @@ Incorrect cast causes a compile-time error or runtime ``ClassCastException``. // ClassCastException during runtime is thrown: let c3 = createShape() as Square + // Number object is created and instanceof works as expected: + let e2 = (new Number(5.0)) instanceof Number // true + ``` diff --git a/linter-4.2/docs/rules/recipe55.md b/linter-4.2/docs/rules/recipe55.md index 2b47bb52508ab4a126c165b41a62693b86879c9b..42eb50236a2d128756bf4570625b9bd0bc6fd247 100644 --- a/linter-4.2/docs/rules/recipe55.md +++ b/linter-4.2/docs/rules/recipe55.md @@ -15,14 +15,25 @@ be done explicitly. ``` - let a = +5 // 5 as number - let b = +"5" // 5 as number - let c = -5 // -5 as number - let d = -"5" // -5 as number - let e = ~5 // -6 as number - let f = ~"5" // -6 as number + let a = +5 // 5 as number + let b = +"5" // 5 as number + let c = -5 // -5 as number + let d = -"5" // -5 as number + let e = ~5 // -6 as number + let f = ~"5" // -6 as number let g = +"string" // NaN as number + function returnTen(): string { + return "-10" + } + + function returnString(): string { + return "string" + } + + let x = +returnTen() // -10 as number + let y = +returnString() // NaN + ``` ## ArkTS @@ -30,19 +41,25 @@ be done explicitly. ``` - let a = +5 // 5 as number - let b = +"5" // Compile-time error - let c = -5 // -5 as number - let d = -"5" // Compile-time error - let e = ~5 // -6 as number - let f = ~"5" // Compile-time error + let a = +5 // 5 as number + let b = +"5" // Compile-time error + let c = -5 // -5 as number + let d = -"5" // Compile-time error + let e = ~5 // -6 as number + let f = ~"5" // Compile-time error let g = +"string" // Compile-time error -``` + function returnTen(): string { + return "-10" + } + + function returnString(): string { + return "string" + } -## See also + let x = +returnTen() // Compile-time error + let y = +returnString() // Compile-time error -- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) -- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) +``` diff --git a/linter-4.2/docs/rules/recipe56.md b/linter-4.2/docs/rules/recipe56.md deleted file mode 100644 index 8f1cb613ec44ee44206e51be05f75ca7d28b1a25..0000000000000000000000000000000000000000 --- a/linter-4.2/docs/rules/recipe56.md +++ /dev/null @@ -1,54 +0,0 @@ -# Unary ``+`` cannot be used for casting to ``number`` - -Rule ``arkts-no-unary-plus-cast`` - -**Severity: error** - -ArkTS does not support casting from any type to a numeric type -by using the unary ``+`` operator, which can be applied only to -numeric types. - - -## TypeScript - - -``` - - function returnTen(): string { - return "-10" - } - - function returnString(): string { - return "string" - } - - let a = +returnTen() // -10 as number - let b = +returnString() // NaN - -``` - -## ArkTS - - -``` - - function returnTen(): string { - return "-10" - } - - function returnString(): string { - return "string" - } - - let a = +returnTen() // Compile-time error - let b = +returnString() // Compile-time error - -``` - -## See also - -- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) -- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) -- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) - - diff --git a/linter-4.2/docs/rules/recipe59.md b/linter-4.2/docs/rules/recipe59.md index d64602e17550c8857100b5de5897a415472d816e..d2c937e46ea7a8f1d18950868e5e5e4bc8b24070 100644 --- a/linter-4.2/docs/rules/recipe59.md +++ b/linter-4.2/docs/rules/recipe59.md @@ -32,8 +32,8 @@ changed at runtime. Thus the operation of deleting a property makes no sense. // and assign null to mark value absence: class Point { - x: number | null - y: number | null + x: number | null = 0 + y: number | null = 0 } let p = new Point() diff --git a/linter-4.2/docs/rules/recipe61.md b/linter-4.2/docs/rules/recipe61.md deleted file mode 100644 index e5bdfd14abd026bf364762ae3044274ce249ec5a..0000000000000000000000000000000000000000 --- a/linter-4.2/docs/rules/recipe61.md +++ /dev/null @@ -1,71 +0,0 @@ -# Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types - -Rule ``arkts-no-polymorphic-binops`` - -**Severity: error** - -ArkTS allows applying binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, -``>>``, ``>>>``, ``&``, ``^`` and ``|`` only to values of numeric types. -Implicit casts from other types to numeric types are prohibited and cause -compile-time errors. - - -## TypeScript - - -``` - - let a = (5 & 5) // 5 - let b = (5.5 & 5.5) // 5, not 5.5 - let c = (5 | 5) // 5 - let d = (5.5 | 5.5) // 5, not 5.5 - - enum Direction { - Up = -1, - Down - } - let e = Direction.Up >> 1 // -1 - let f = Direction.Up >>> 1 // 2147483647 - - let g = ("10" as any) << 1 // 20 - let h = ("str" as any) << 1 // 0 - - let i = 10 * 5 - let j = 10 / 5 - let k = 10 % 5 - let l = 10 - 5 - -``` - -## ArkTS - - -``` - - let a = (5 & 5) // 5 - let b = (5.5 & 5.5) // Compile-time error - let c = (5 | 5) // 5 - let d = (5.5 | 5.5) // Compile-time error - - enum Direction { - Up, - Down - } - - let e = Direction.Up >> 1 // 0 - let f = Direction.Up >>> 1 // 0 - - let i = 10 * 5 - let j = 10 / 5 - let k = 10 % 5 - let l = 10 - 5 - -``` - -## See also - -- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) -- Recipe 056: Unary ``+`` cannot be used for casting to ``number`` (``arkts-no-unary-plus-cast``) -- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) - - diff --git a/linter-4.2/docs/rules/recipe63.md b/linter-4.2/docs/rules/recipe63.md deleted file mode 100644 index 47b26ae720c5bd3eb66b955de31c11a1847fc844..0000000000000000000000000000000000000000 --- a/linter-4.2/docs/rules/recipe63.md +++ /dev/null @@ -1,55 +0,0 @@ -# Binary ``+`` operator supports implicit casts only for numbers and strings - -Rule ``arkts-no-polymorphic-plus`` - -**Severity: error** - -ArkTS supports implicit casts for ``+`` only for strings and numbers. -Elsewhere, any form of an explicit cast to string is required. - - -## TypeScript - - -``` - - enum E { E1, E2 } - - let a = 10 + 32 // 42 - let b = E.E1 + 10 // 10 - let c = 10 + "5" // "105" - - let d = "5" + E.E2 // "51" - let e = "Hello, " + "world!" // "Hello, world!" - let f = "string" + true // "stringtrue" - - let g = (new Object()) + "string" // "[object Object]string" - -``` - -## ArkTS - - -``` - - enum E { E1, E2 } - - let a = 10 + 32 // 42 - let b = E.E1 + 10 // 10 - let c = 10 + "5" // "105" - - let d = "5" + E.E2 // "51" - let e = "Hello, " + "world!" // "Hello, world!" - let f = "string" + true // "stringtrue" - - let g = (new Object()).toString() + "string" - -``` - -## See also - -- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) -- Recipe 056: Unary ``+`` cannot be used for casting to ``number`` (``arkts-no-unary-plus-cast``) -- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) - - diff --git a/linter-4.2/docs/rules/recipe65.md b/linter-4.2/docs/rules/recipe65.md index b72b699c33296ad215ccdf06bb8dbe0d775ec4ec..89e956fcb88b38e57c2e7194f596a405bbee78e2 100644 --- a/linter-4.2/docs/rules/recipe65.md +++ b/linter-4.2/docs/rules/recipe65.md @@ -16,16 +16,15 @@ a type. ``` - class X {} + class X { + // ... + } let a = (new X()) instanceof Object // true - let b = (new X()) instanceof X // true - // left operand is a type: - let c = X instanceof Object // true - let d = X instanceof X // false + let b = (new X()) instanceof X // true - // left operand is not of type any - let e = (5.0 as Number) instanceof Number // false + let c = X instanceof Object // true, left operand is a type + let d = X instanceof X // false, left operand is a type ``` @@ -34,16 +33,15 @@ a type. ``` - class X {} + class X { + // ... + } let a = (new X()) instanceof Object // true - let b = (new X()) instanceof X // true - // left operand is a type: - let c = X instanceof Object // Compile-time error - let d = X instanceof X // Compile-time error + let b = (new X()) instanceof X // true - // left operand may be of any reference type, like number - let e = (5.0 as Number) instanceof Number // true + let c = X instanceof Object // Compile-time error, left operand is a type + let d = X instanceof X // Compile-time error, left operand is a type ``` diff --git a/linter-4.2/docs/rules/recipe69.md b/linter-4.2/docs/rules/recipe69.md index 50d253b2ff54bfdc67412df656e6216b2917ef5f..80725b25c2840f4e39e3029f6947af2bfb57c3e8 100644 --- a/linter-4.2/docs/rules/recipe69.md +++ b/linter-4.2/docs/rules/recipe69.md @@ -34,11 +34,11 @@ using a temporary variable, where applicable) can be used for replacement. one = two two = tmp - let data: Number[] = [1,2,3,4] + let data: Number[] = [1, 2, 3, 4] let head = data[0] - let tail = new Number[data.length - 1] + let tail: Number[] = [] for (let i = 1; i < data.length; ++i) { - tail[i - 1] = data[i] + tail.push(data[i]) } ``` diff --git a/linter-4.2/docs/rules/recipe79.md b/linter-4.2/docs/rules/recipe79.md index 56ac1ea4fe71ac3ff98de23ffd33c202c6ef7458..15f916438120bd1e272a20cc4053f159675c80a6 100644 --- a/linter-4.2/docs/rules/recipe79.md +++ b/linter-4.2/docs/rules/recipe79.md @@ -17,7 +17,9 @@ be omitted. try { // some code } - catch (a: unknown) {} + catch (a: unknown) { + // handle error + } ``` @@ -29,7 +31,9 @@ be omitted. try { // some code } - catch (a) {} + catch (a) { + // handle error + } ``` diff --git a/linter-4.2/docs/rules/recipe8.md b/linter-4.2/docs/rules/recipe8.md index fd3e9e1004eb6050b4aff873026d39400e7bfc5b..32767236302c44ee45b242d7338080cbb8f75c20 100644 --- a/linter-4.2/docs/rules/recipe8.md +++ b/linter-4.2/docs/rules/recipe8.md @@ -1,6 +1,6 @@ # Use explicit types instead of ``any``, ``unknown`` -Rule ``arkts-no-any-undefined-unknown`` +Rule ``arkts-no-any-unknown`` **Severity: error** diff --git a/linter-4.2/docs/rules/recipe90.md b/linter-4.2/docs/rules/recipe90.md index 0613f6913d23d1eef21feed846cb1e9e10136829..2ef93392aa5625d59e0633641fabdb69460ef680 100644 --- a/linter-4.2/docs/rules/recipe90.md +++ b/linter-4.2/docs/rules/recipe90.md @@ -16,6 +16,7 @@ explicitly. ``` + // Compile-time error with noImplicitAny function f(x: number) { if (x <= 0) { return x @@ -23,6 +24,7 @@ explicitly. return g(x) } + // Compile-time error with noImplicitAny function g(x: number) { return f(x - 1) } diff --git a/linter-4.2/docs/rules/recipe93.md b/linter-4.2/docs/rules/recipe93.md index ceb0cacf5618c9c4847d9c33c0193ecda6c91a1d..ab4bce316abf01eaf8491b7d1c1d055c5ddd5527 100644 --- a/linter-4.2/docs/rules/recipe93.md +++ b/linter-4.2/docs/rules/recipe93.md @@ -14,7 +14,7 @@ ArkTS does not support the usage of ``this`` inside stand-alone functions. ``` function foo(i: number) { - this.count = i + this.count = i // Compile-time error only with noImplicitThis } class A { diff --git a/linter-4.2/src/CookBookMsg.ts b/linter-4.2/src/CookBookMsg.ts index 57e28c882afa5a3e0efa98ee3e4acb3ed57fbb53..50cf78a1b2bfdaec214ebe882ecbf34c20956a7b 100644 --- a/linter-4.2/src/CookBookMsg.ts +++ b/linter-4.2/src/CookBookMsg.ts @@ -27,7 +27,7 @@ cookBookTag[ 4 ] = 'Use unique names for types, namespaces, etc. (arkts-unique-n cookBookTag[ 5 ] = 'Use "let" instead of "var" (arkts-no-var)'; cookBookTag[ 6 ] = ''; cookBookTag[ 7 ] = ''; -cookBookTag[ 8 ] = 'Use explicit types instead of "any", "unknown" (arkts-no-any-undefined-unknown)'; +cookBookTag[ 8 ] = 'Use explicit types instead of "any", "unknown" (arkts-no-any-unknown)'; cookBookTag[ 9 ] = ''; cookBookTag[ 10 ] = '"bigint" is not a builtin type, suffix "n" for numeric literals is not supported (arkts-no-n-suffix)'; cookBookTag[ 11 ] = ''; @@ -75,14 +75,14 @@ cookBookTag[ 52 ] = 'Attempt to access an undefined property is a compile-time e cookBookTag[ 53 ] = 'Only "as T" syntax is supported for type casts (arkts-as-casts)'; cookBookTag[ 54 ] = 'JSX expressions are not supported (arkts-no-jsx)'; cookBookTag[ 55 ] = 'Unary operators "+", "-" and "~" work only on numbers (arkts-no-polymorphic-unops)'; -cookBookTag[ 56 ] = 'Unary "+" cannot be used for casting to "number" (arkts-no-unary-plus-cast)'; +cookBookTag[ 56 ] = ''; cookBookTag[ 57 ] = ''; cookBookTag[ 58 ] = ''; cookBookTag[ 59 ] = '"delete" operator is not supported (arkts-no-delete)'; cookBookTag[ 60 ] = '"typeof" operator is allowed only in expression contexts (arkts-no-type-query)'; -cookBookTag[ 61 ] = 'Binary operators "*", "/", "%", "-", "<<", ">>", ">>>", "&", "^" and "|" work only on numeric types (arkts-no-polymorphic-binops)'; +cookBookTag[ 61 ] = ''; cookBookTag[ 62 ] = ''; -cookBookTag[ 63 ] = 'Binary "+" operator supports implicit casts only for numbers and strings (arkts-no-polymorphic-plus)'; +cookBookTag[ 63 ] = ''; cookBookTag[ 64 ] = ''; cookBookTag[ 65 ] = '"instanceof" operator is partially supported (arkts-instanceof-ref-types)'; cookBookTag[ 66 ] = '"in" operator is not supported (arkts-no-in)'; @@ -134,7 +134,7 @@ cookBookTag[ 111 ] = 'Enumeration members can be initialized only with compile t cookBookTag[ 112 ] = ''; cookBookTag[ 113 ] = '"enum" declaration merging is not supported (arkts-no-enum-merging)'; cookBookTag[ 114 ] = 'Namespaces cannot be used as objects (arkts-no-ns-as-obj)'; -cookBookTag[ 115 ] = 'Scripts and modules (arkts-no-scripts)'; +cookBookTag[ 115 ] = ''; cookBookTag[ 116 ] = 'Non-declaration statements in namespaces are not supported (arkts-no-ns-statements)'; cookBookTag[ 117 ] = ''; cookBookTag[ 118 ] = 'Special import type declarations are not supported (arkts-no-special-imports)'; diff --git a/linter-4.2/src/TypeScriptLinter.ts b/linter-4.2/src/TypeScriptLinter.ts index ace430886a2d0790c9c3ffd5240653377b865904..8afdf97da391f54b78b5d190040cb8515a7a0c03 100644 --- a/linter-4.2/src/TypeScriptLinter.ts +++ b/linter-4.2/src/TypeScriptLinter.ts @@ -1402,6 +1402,12 @@ export class TypeScriptLinter { !Utils.relatedByInheritanceOrIdentical(targetType, exprType) ) this.incrementCounters(tsAsExpr, FaultID.StructuralIdentity); + // check for rule#65: 'number as Number' and 'boolean as Boolean' are disabled + if( + ( Utils.isNumberType(exprType) && targetType.getSymbol()?.getName() === 'Number' ) || + ( Utils.isBooleanType(exprType) && targetType.getSymbol()?.getName() === 'Boolean' ) + ) + this.incrementCounters(node, FaultID.TypeAssertion); } private handleTypeReference(node: ts.Node) { diff --git a/linter-4.2/test/instanceof.ts b/linter-4.2/test/instanceof.ts index 7f04b131b0decc7c28b286b74fdafa53ddd97a01..2289a2292c1ff992a31e34c8bc412a68d6d45b19 100644 --- a/linter-4.2/test/instanceof.ts +++ b/linter-4.2/test/instanceof.ts @@ -28,3 +28,13 @@ const e = (5.0 as number) instanceof Number; // false const f = (X | String) instanceof Object; const g = 3 instanceof Number; + + +let bad2Number = 5.0 as Number; +let pi = 3.14; +bad2Number = pi as Number; + +let bad2Boolean = true as Boolean; +let bad2Boolean = a as Boolean; + + diff --git a/linter-4.2/test/instanceof.ts.strict.json b/linter-4.2/test/instanceof.ts.strict.json index f9d548166e325ea9f11bd1b7a346c6e59aa69005..d95a4cf3335d3f034b90b9410f667a1c8f5e5263 100644 --- a/linter-4.2/test/instanceof.ts.strict.json +++ b/linter-4.2/test/instanceof.ts.strict.json @@ -33,6 +33,26 @@ "line": 30, "column": 11, "problem": "InstanceofUnsupported" + }, + { + "line": 33, + "column": 18, + "problem": "TypeAssertion" + }, + { + "line": 35, + "column": 14, + "problem": "TypeAssertion" + }, + { + "line": 37, + "column": 19, + "problem": "TypeAssertion" + }, + { + "line": 38, + "column": 19, + "problem": "TypeAssertion" } ] } \ No newline at end of file diff --git a/linter/.gitignore b/linter/.gitignore index 3ded455fc811af5ac325bb4ed532facefecd86a4..4797db793b998b8c2ea246115378791d451072f7 100644 --- a/linter/.gitignore +++ b/linter/.gitignore @@ -2,6 +2,7 @@ build dist bundle node_modules +cookbook_convertor/md *.tsbuildinfo .vs .vscode diff --git a/linter/docs/rules/recipe1.md b/linter/docs/rules/recipe1.md index 317d04c6bd75c5d7c80e2e19a7553595833174ac..cda73e56f251fa409b819241734af7ca03fc3039 100644 --- a/linter/docs/rules/recipe1.md +++ b/linter/docs/rules/recipe1.md @@ -27,7 +27,7 @@ data by numeric indices. ``` class X { - public name: number + public name: number = 0 } let x = {name: 1} console.log(x.name) diff --git a/linter/docs/rules/recipe115.md b/linter/docs/rules/recipe115.md deleted file mode 100644 index ee73f68fd25bfc22657de9f15ea50dd826f62462..0000000000000000000000000000000000000000 --- a/linter/docs/rules/recipe115.md +++ /dev/null @@ -1,21 +0,0 @@ -# Scripts and modules - -Rule ``arkts-no-scripts`` - -**Severity: error** - -In general, scripts and modules in ArkTS are very close to TypeScript. -Differences are described in separate recipes. - - -## See also - -- Recipe 118: Special import type declarations are not supported (``arkts-no-special-imports``) -- Recipe 119: Importing a module for side-effects only is not supported (``arkts-no-side-effects-imports``) -- Recipe 120: ``import default as ...`` is not supported (``arkts-no-import-default-as``) -- Recipe 121: ``require`` and ``import`` assignment are not supported (``arkts-no-require``) -- Recipe 124: Export list declaration is not supported (``arkts-no-export-list-decl``) -- Recipe 125: Re-exporting is supported with restrictions (``arkts-limited-reexport``) -- Recipe 126: ``export = ...`` assignment is not supported (``arkts-no-export-assignment``) - - diff --git a/linter/docs/rules/recipe118.md b/linter/docs/rules/recipe118.md index 0041552fdb013d8acf3a5c3078f2ebc668725250..f625bc3e982353617c9dd28f7c6d67ff886e1e6d 100644 --- a/linter/docs/rules/recipe118.md +++ b/linter/docs/rules/recipe118.md @@ -14,10 +14,10 @@ Use ordinary import instead. ``` // Re-using the same import - import { APIResponseType } from "./api" + import { APIResponseType } from "api" // Explicitly use import type - import type { APIResponseType } from "./api" + import type { APIResponseType } from "api" ``` @@ -26,7 +26,7 @@ Use ordinary import instead. ``` - import { APIResponseType } from "./api" + import { APIResponseType } from "api" ``` diff --git a/linter/docs/rules/recipe128.md b/linter/docs/rules/recipe128.md index 9a5ccebd49091bd5476bf510ae314d8579f3c80d..ddba6753b7c5499be4977aeec2bc5810c359c4f4 100644 --- a/linter/docs/rules/recipe128.md +++ b/linter/docs/rules/recipe128.md @@ -25,7 +25,7 @@ own mechanisms for interoperating with JavaScript. ``` // Import what you need from the original module - import { normalize } from "../someModule" + import { normalize } from "someModule" ``` diff --git a/linter/docs/rules/recipe130.md b/linter/docs/rules/recipe130.md index da2aada018a1563dd2c1f404b017a3434b285fa7..4a5c602e60d71e12f414a52a30e3741afa26b6a7 100644 --- a/linter/docs/rules/recipe130.md +++ b/linter/docs/rules/recipe130.md @@ -35,7 +35,7 @@ import is a compile-time, not a runtime feature. Use ordinary syntax for } // in program - import { mathLib } from "./math-lib" + import { mathLib } from "math-lib" mathLib.isPrime(2) ``` diff --git a/linter/docs/rules/recipe131.md b/linter/docs/rules/recipe131.md index c9f6e9c22c3de7ef824bd6054afee845478aceed..a103967cd268676efdca9c305a6a8285ef13c622 100644 --- a/linter/docs/rules/recipe131.md +++ b/linter/docs/rules/recipe131.md @@ -13,7 +13,7 @@ has its own mechanisms for interoperating with JavaScript. ``` - import { something } from "./module.js" + import { something } from "module.js" ``` @@ -22,7 +22,7 @@ has its own mechanisms for interoperating with JavaScript. ``` - import { something } from "./module" + import { something } from "module" ``` diff --git a/linter/docs/rules/recipe133.md b/linter/docs/rules/recipe133.md index 222bfdee09033650658d89ce1087c5782bead853..ab2f0a51e351586caadd1801f03aa0fedc8d5fdb 100644 --- a/linter/docs/rules/recipe133.md +++ b/linter/docs/rules/recipe133.md @@ -14,7 +14,7 @@ import syntax instead. ``` - const zipUtil = await import("./utils/create-zip-file") + const zipUtil = await import("utils/create-zip-file") ``` @@ -23,7 +23,7 @@ import syntax instead. ``` - import { zipUtil } from "./utils/create-zip-file" + import { zipUtil } from "utils/create-zip-file" ``` diff --git a/linter/docs/rules/recipe135.md b/linter/docs/rules/recipe135.md index 545a49b9b8351cd67693e04219743eea6bbb4f07..5e7bb88359c03032d55eb6606419f5a5c08d9f22 100644 --- a/linter/docs/rules/recipe135.md +++ b/linter/docs/rules/recipe135.md @@ -15,9 +15,10 @@ namespaces instead. ``` var C = (function() { - function C(n) { - this.p = n + function C(n: number) { + this.p = n // Compile-time error only with noImplicitThis } + C.staticProperty = 0 return C })() C.staticProperty = 1 diff --git a/linter/docs/rules/recipe136.md b/linter/docs/rules/recipe136.md index eb2ada7062458b5bd9243fad473283a77161429c..550b95b54e40f1f03f13f26b9b4e52e9909d9add 100644 --- a/linter/docs/rules/recipe136.md +++ b/linter/docs/rules/recipe136.md @@ -15,7 +15,7 @@ applicable to the static typing. ``` var C = function(p) { - this.p = p + this.p = p // Compile-time error only with noImplicitThis } C.prototype = { diff --git a/linter/docs/rules/recipe137.md b/linter/docs/rules/recipe137.md index 588cc70f46e523414ec8c99dc61aad374f963c14..5cb8d691d69879fb83eece870004ac011d61267b 100644 --- a/linter/docs/rules/recipe137.md +++ b/linter/docs/rules/recipe137.md @@ -30,7 +30,7 @@ objects with dynamically changed layout are not supported. export let abc : number = 0 // file2 - import * as M from "../file1" + import * as M from "file1" M.abc = 200 diff --git a/linter/docs/rules/recipe138.md b/linter/docs/rules/recipe138.md index f97ec50ae8cf49b9c6d2ed321ed69e7603f3f779..7dfec46f8cc36c700f907fd31e80ff46563bcaaf 100644 --- a/linter/docs/rules/recipe138.md +++ b/linter/docs/rules/recipe138.md @@ -8,6 +8,9 @@ Currently ArkTS does not support utility types from TypeScript extensions to the standard library (``Omit``, ``Pick``, etc.). Exceptions are: ``Partial``, ``Record``. +For ``Record`` type, the type of value must be either optional or unioned with +the ``undefined`` type. + ## TypeScript @@ -22,6 +25,21 @@ standard library (``Omit``, ``Pick``, etc.). Exceptions are: ``Partial``, type QuantumPerson = Omit + let persons : Record = { + "Alice": { + name: "Alice", + age: 32, + location: "Shanghai" + }, + "Bob": { + name: "Bob", + age: 48, + location: "New York" + } + } + console.log(persons["Bob"].age) + console.log(persons["Rob"].age) // Runtime exception + ``` ## ArkTS @@ -30,14 +48,34 @@ standard library (``Omit``, ``Pick``, etc.). Exceptions are: ``Partial``, ``` class Person { - name: string - age: number - location: string + name: string = "" + age: number = 0 + location: string = "" } class QuantumPerson { - name: string - age: number + name: string = "" + age: number = 0 + } + + type OptionalPerson = Person | undefined + let persons : Record = { + // Or: + // let persons : Record = { + "Alice": { + name: "Alice", + age: 32, + location: "Shanghai" + }, + "Bob": { + name: "Bob", + age: 48, + location: "New York" + } + } + console.log(persons["Bob"]!.age) + if (persons["Rob"]) { // Explicit value check, no runtime exception + console.log(persons["Rob"].age) } ``` diff --git a/linter/docs/rules/recipe139.md b/linter/docs/rules/recipe139.md index 5b27d1ebfa1009bd3986a339da8172aec5b19fef..70fd6896612202816c9229291c7c470d499e8e00 100644 --- a/linter/docs/rules/recipe139.md +++ b/linter/docs/rules/recipe139.md @@ -49,15 +49,17 @@ this rule and their layout cannot be changed in runtime. // ... } - function readImage( + async function readImage( path: string, callback: (err: Error, image: MyImage) => void ) : Promise { - // async implementation + // In real world, the implementation is more complex, + // involving real network / DB logic, etc. + return await new MyImage() } function readImageSync(path: string) : MyImage { - // sync implementation + return new MyImage() } ``` diff --git a/linter/docs/rules/recipe142.md b/linter/docs/rules/recipe142.md index cca78dc76637bdb0eda7fa5750cb6a3bc51bc497..7cef054e7cba81bc32feedebfb1e795d46ccd299 100644 --- a/linter/docs/rules/recipe142.md +++ b/linter/docs/rules/recipe142.md @@ -37,7 +37,7 @@ does not support literal types. let y : number[] = [10, 20] class Label { - text : string + text : string = "" } // Type 'Label': diff --git a/linter/docs/rules/recipe143.md b/linter/docs/rules/recipe143.md index 946b66efabc033db1d1035ab972de036f8cd2872..9dbec44af7a89f9264e0d8d8b0957a770ff3f0ae 100644 --- a/linter/docs/rules/recipe143.md +++ b/linter/docs/rules/recipe143.md @@ -15,7 +15,7 @@ in runtime does not make sense for the statically typed language. Use ordinary ``` - import { obj } from "./something.json" assert { type: "json" } + import { obj } from "something.json" assert { type: "json" } ``` @@ -25,7 +25,7 @@ in runtime does not make sense for the statically typed language. Use ordinary ``` // Correctness of importing T will be checked in compile-time: - import { something } from "./module" + import { something } from "module" ``` diff --git a/linter/docs/rules/recipe145.md b/linter/docs/rules/recipe145.md index 37e7be51f165a952926ccaf4efa3e2876798a817..022f436ff45b81710ec06c255bae2363dc600dcd 100644 --- a/linter/docs/rules/recipe145.md +++ b/linter/docs/rules/recipe145.md @@ -16,15 +16,21 @@ following flags should be turned on: ``noImplicitReturns``, ``` class C { - n: number - s: string + n: number // Compile-time error only with strictPropertyInitialization + s: string // Compile-time error only with strictPropertyInitialization } + // Compile-time error only with noImplicitReturns function foo(s: string): string { - console.log(s) + if (s != "") { + console.log(s) + return s + } else { + console.log(s) + } } - let n: number = null + let n: number = null // Compile-time error only with strictNullChecks ``` @@ -50,7 +56,7 @@ following flags should be turned on: ``noImplicitReturns``, ## See also -- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-undefined-unknown``) +- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-unknown``) - Recipe 146: Switching off type checks with in-place comments is not allowed (``arkts-strict-typing-required``) diff --git a/linter/docs/rules/recipe146.md b/linter/docs/rules/recipe146.md index f00a66b1563b5c3d4fac8f031a578988df342655..6426faf2820b61e31a2fde93e7bdaba0d591392c 100644 --- a/linter/docs/rules/recipe146.md +++ b/linter/docs/rules/recipe146.md @@ -20,9 +20,10 @@ with special comments is not allowed. In particular, ``@ts-ignore`` and // Some code with switched off type checker // ... - // @ts-ignore let s1: string = null // No error, type checker suppressed - let s2: string = null // Compile-time error + + // @ts-ignore + let s2: string = null // No error, type checker suppressed ``` @@ -38,7 +39,7 @@ with special comments is not allowed. In particular, ``@ts-ignore`` and ## See also -- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-undefined-unknown``) +- Recipe 008: Use explicit types instead of ``any``, ``unknown`` (``arkts-no-any-unknown``) - Recipe 145: Strict type checking is enforced (``arkts-strict-typing``) diff --git a/linter/docs/rules/recipe147.md b/linter/docs/rules/recipe147.md index 6a81f41c8e315e4530e5fe285ca02d2cbbf24414..de1f456d1eb55e88aed93e13045a3157ed1b05fe 100644 --- a/linter/docs/rules/recipe147.md +++ b/linter/docs/rules/recipe147.md @@ -24,4 +24,3 @@ through importing ArkTS code base. Imports in reverse direction are supported. ``` - diff --git a/linter/docs/rules/recipe17.md b/linter/docs/rules/recipe17.md index 4dd591c0eb9e6cf06a34a85862ae84f7057d2a83..93066f260be9ab7a3d18f5975b00278abd6fb723 100644 --- a/linter/docs/rules/recipe17.md +++ b/linter/docs/rules/recipe17.md @@ -32,7 +32,7 @@ ArkTS does not allow indexed signatures, use arrays instead. ``` class X { - public f: string[] + public f: string[] = [] } let myArray: X = new X() diff --git a/linter/docs/rules/recipe2.md b/linter/docs/rules/recipe2.md index 623cbff522305e062b19fe33f58679239e9afd37..04a96f96710df337f784ec458939864ec04f927b 100644 --- a/linter/docs/rules/recipe2.md +++ b/linter/docs/rules/recipe2.md @@ -29,7 +29,7 @@ and cannot be changed at runtime. ``` class SomeClass { - public someProperty : string + public someProperty : string = "" } let o = new SomeClass() diff --git a/linter/docs/rules/recipe40.md b/linter/docs/rules/recipe40.md index 9fd22580fbf472bf9bebc48b03bca25c45d5cced..dd4221b1457b466a4de5876eb63a5733c817c18d 100644 --- a/linter/docs/rules/recipe40.md +++ b/linter/docs/rules/recipe40.md @@ -28,8 +28,8 @@ types in place. Declare classes and interfaces explicitly instead. ``` class O { - x: number - y: number + x: number = 0 + y: number = 0 } let o: O = {x: 2, y: 3} diff --git a/linter/docs/rules/recipe45.md b/linter/docs/rules/recipe45.md index 20680c932cca974c8ba607d0e640b81b7697af7b..70f14066e4d58cd71b81e1178978f4aa176cdbb5 100644 --- a/linter/docs/rules/recipe45.md +++ b/linter/docs/rules/recipe45.md @@ -13,7 +13,8 @@ to be explicitly specified. ``` - let f = (s) => { // type any is assumed + // Compile-time error only with noImplicitAny: + let f = (s /* type any is assumed */) => { console.log(s) } diff --git a/linter/docs/rules/recipe51.md b/linter/docs/rules/recipe51.md index 9b6ddc1fd820b6ee7dab6b681e90068ae0c04bbf..700a2409c4924fa197aee56960e8de244a85f5d7 100644 --- a/linter/docs/rules/recipe51.md +++ b/linter/docs/rules/recipe51.md @@ -29,7 +29,7 @@ may be specified. ``` interface C { - foo() + foo(): void } class C1 implements C { diff --git a/linter/docs/rules/recipe52.md b/linter/docs/rules/recipe52.md index 91042ae7740cc4270ead455db209cd7b71fe9219..f4ff3fd4b324df772894a9034fb7c0d41370f369 100644 --- a/linter/docs/rules/recipe52.md +++ b/linter/docs/rules/recipe52.md @@ -19,7 +19,7 @@ existence during compilation. let n = person["name"] let e = person["isEmployee"] - let s = person["office"] // undefined + let s = person["office"] // Compile-time error only with noImplicitAny ``` diff --git a/linter/docs/rules/recipe53.md b/linter/docs/rules/recipe53.md index 17c22a056818e171f8dee46ffb6123ba01f2ebd6..ea6c5a8a17992770b01f502dc657cad202b39303 100644 --- a/linter/docs/rules/recipe53.md +++ b/linter/docs/rules/recipe53.md @@ -8,6 +8,10 @@ ArkTS supports ``as`` keyword as the only syntax for type casts. Incorrect cast causes a compile-time error or runtime ``ClassCastException``. ```` syntax for type casts is not supported. +However, if a **primitive** type (e.g. a ``number`` or a ``boolean``) must be +cast to the reference type, this must be done through the ``new ...`` expression +instead of ``as``. + ## TypeScript @@ -31,6 +35,14 @@ Incorrect cast causes a compile-time error or runtime ``ClassCastException``. let c3 = createShape() as Square console.log(c3.y) // undefined + // Important corner case for casting primitives to the boxed counterparts: + // The left operand is not properly boxed here in in runtime + // because "as" has no runtime effect in TypeScript + let e1 = (5.0 as Number) instanceof Number // false + + // Number object is created and instanceof works as expected: + let e2 = (new Number(5.0)) instanceof Number // true + ``` ## ArkTS @@ -51,6 +63,9 @@ Incorrect cast causes a compile-time error or runtime ``ClassCastException``. // ClassCastException during runtime is thrown: let c3 = createShape() as Square + // Number object is created and instanceof works as expected: + let e2 = (new Number(5.0)) instanceof Number // true + ``` diff --git a/linter/docs/rules/recipe55.md b/linter/docs/rules/recipe55.md index 2b47bb52508ab4a126c165b41a62693b86879c9b..42eb50236a2d128756bf4570625b9bd0bc6fd247 100644 --- a/linter/docs/rules/recipe55.md +++ b/linter/docs/rules/recipe55.md @@ -15,14 +15,25 @@ be done explicitly. ``` - let a = +5 // 5 as number - let b = +"5" // 5 as number - let c = -5 // -5 as number - let d = -"5" // -5 as number - let e = ~5 // -6 as number - let f = ~"5" // -6 as number + let a = +5 // 5 as number + let b = +"5" // 5 as number + let c = -5 // -5 as number + let d = -"5" // -5 as number + let e = ~5 // -6 as number + let f = ~"5" // -6 as number let g = +"string" // NaN as number + function returnTen(): string { + return "-10" + } + + function returnString(): string { + return "string" + } + + let x = +returnTen() // -10 as number + let y = +returnString() // NaN + ``` ## ArkTS @@ -30,19 +41,25 @@ be done explicitly. ``` - let a = +5 // 5 as number - let b = +"5" // Compile-time error - let c = -5 // -5 as number - let d = -"5" // Compile-time error - let e = ~5 // -6 as number - let f = ~"5" // Compile-time error + let a = +5 // 5 as number + let b = +"5" // Compile-time error + let c = -5 // -5 as number + let d = -"5" // Compile-time error + let e = ~5 // -6 as number + let f = ~"5" // Compile-time error let g = +"string" // Compile-time error -``` + function returnTen(): string { + return "-10" + } + + function returnString(): string { + return "string" + } -## See also + let x = +returnTen() // Compile-time error + let y = +returnString() // Compile-time error -- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) -- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) +``` diff --git a/linter/docs/rules/recipe56.md b/linter/docs/rules/recipe56.md deleted file mode 100644 index 8f1cb613ec44ee44206e51be05f75ca7d28b1a25..0000000000000000000000000000000000000000 --- a/linter/docs/rules/recipe56.md +++ /dev/null @@ -1,54 +0,0 @@ -# Unary ``+`` cannot be used for casting to ``number`` - -Rule ``arkts-no-unary-plus-cast`` - -**Severity: error** - -ArkTS does not support casting from any type to a numeric type -by using the unary ``+`` operator, which can be applied only to -numeric types. - - -## TypeScript - - -``` - - function returnTen(): string { - return "-10" - } - - function returnString(): string { - return "string" - } - - let a = +returnTen() // -10 as number - let b = +returnString() // NaN - -``` - -## ArkTS - - -``` - - function returnTen(): string { - return "-10" - } - - function returnString(): string { - return "string" - } - - let a = +returnTen() // Compile-time error - let b = +returnString() // Compile-time error - -``` - -## See also - -- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) -- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) -- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) - - diff --git a/linter/docs/rules/recipe59.md b/linter/docs/rules/recipe59.md index d64602e17550c8857100b5de5897a415472d816e..d2c937e46ea7a8f1d18950868e5e5e4bc8b24070 100644 --- a/linter/docs/rules/recipe59.md +++ b/linter/docs/rules/recipe59.md @@ -32,8 +32,8 @@ changed at runtime. Thus the operation of deleting a property makes no sense. // and assign null to mark value absence: class Point { - x: number | null - y: number | null + x: number | null = 0 + y: number | null = 0 } let p = new Point() diff --git a/linter/docs/rules/recipe61.md b/linter/docs/rules/recipe61.md deleted file mode 100644 index e5bdfd14abd026bf364762ae3044274ce249ec5a..0000000000000000000000000000000000000000 --- a/linter/docs/rules/recipe61.md +++ /dev/null @@ -1,71 +0,0 @@ -# Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types - -Rule ``arkts-no-polymorphic-binops`` - -**Severity: error** - -ArkTS allows applying binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, -``>>``, ``>>>``, ``&``, ``^`` and ``|`` only to values of numeric types. -Implicit casts from other types to numeric types are prohibited and cause -compile-time errors. - - -## TypeScript - - -``` - - let a = (5 & 5) // 5 - let b = (5.5 & 5.5) // 5, not 5.5 - let c = (5 | 5) // 5 - let d = (5.5 | 5.5) // 5, not 5.5 - - enum Direction { - Up = -1, - Down - } - let e = Direction.Up >> 1 // -1 - let f = Direction.Up >>> 1 // 2147483647 - - let g = ("10" as any) << 1 // 20 - let h = ("str" as any) << 1 // 0 - - let i = 10 * 5 - let j = 10 / 5 - let k = 10 % 5 - let l = 10 - 5 - -``` - -## ArkTS - - -``` - - let a = (5 & 5) // 5 - let b = (5.5 & 5.5) // Compile-time error - let c = (5 | 5) // 5 - let d = (5.5 | 5.5) // Compile-time error - - enum Direction { - Up, - Down - } - - let e = Direction.Up >> 1 // 0 - let f = Direction.Up >>> 1 // 0 - - let i = 10 * 5 - let j = 10 / 5 - let k = 10 % 5 - let l = 10 - 5 - -``` - -## See also - -- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) -- Recipe 056: Unary ``+`` cannot be used for casting to ``number`` (``arkts-no-unary-plus-cast``) -- Recipe 063: Binary ``+`` operator supports implicit casts only for numbers and strings (``arkts-no-polymorphic-plus``) - - diff --git a/linter/docs/rules/recipe63.md b/linter/docs/rules/recipe63.md deleted file mode 100644 index 47b26ae720c5bd3eb66b955de31c11a1847fc844..0000000000000000000000000000000000000000 --- a/linter/docs/rules/recipe63.md +++ /dev/null @@ -1,55 +0,0 @@ -# Binary ``+`` operator supports implicit casts only for numbers and strings - -Rule ``arkts-no-polymorphic-plus`` - -**Severity: error** - -ArkTS supports implicit casts for ``+`` only for strings and numbers. -Elsewhere, any form of an explicit cast to string is required. - - -## TypeScript - - -``` - - enum E { E1, E2 } - - let a = 10 + 32 // 42 - let b = E.E1 + 10 // 10 - let c = 10 + "5" // "105" - - let d = "5" + E.E2 // "51" - let e = "Hello, " + "world!" // "Hello, world!" - let f = "string" + true // "stringtrue" - - let g = (new Object()) + "string" // "[object Object]string" - -``` - -## ArkTS - - -``` - - enum E { E1, E2 } - - let a = 10 + 32 // 42 - let b = E.E1 + 10 // 10 - let c = 10 + "5" // "105" - - let d = "5" + E.E2 // "51" - let e = "Hello, " + "world!" // "Hello, world!" - let f = "string" + true // "stringtrue" - - let g = (new Object()).toString() + "string" - -``` - -## See also - -- Recipe 055: Unary operators ``+``, ``-`` and ``~`` work only on numbers (``arkts-no-polymorphic-unops``) -- Recipe 056: Unary ``+`` cannot be used for casting to ``number`` (``arkts-no-unary-plus-cast``) -- Recipe 061: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types (``arkts-no-polymorphic-binops``) - - diff --git a/linter/docs/rules/recipe65.md b/linter/docs/rules/recipe65.md index b72b699c33296ad215ccdf06bb8dbe0d775ec4ec..89e956fcb88b38e57c2e7194f596a405bbee78e2 100644 --- a/linter/docs/rules/recipe65.md +++ b/linter/docs/rules/recipe65.md @@ -16,16 +16,15 @@ a type. ``` - class X {} + class X { + // ... + } let a = (new X()) instanceof Object // true - let b = (new X()) instanceof X // true - // left operand is a type: - let c = X instanceof Object // true - let d = X instanceof X // false + let b = (new X()) instanceof X // true - // left operand is not of type any - let e = (5.0 as Number) instanceof Number // false + let c = X instanceof Object // true, left operand is a type + let d = X instanceof X // false, left operand is a type ``` @@ -34,16 +33,15 @@ a type. ``` - class X {} + class X { + // ... + } let a = (new X()) instanceof Object // true - let b = (new X()) instanceof X // true - // left operand is a type: - let c = X instanceof Object // Compile-time error - let d = X instanceof X // Compile-time error + let b = (new X()) instanceof X // true - // left operand may be of any reference type, like number - let e = (5.0 as Number) instanceof Number // true + let c = X instanceof Object // Compile-time error, left operand is a type + let d = X instanceof X // Compile-time error, left operand is a type ``` diff --git a/linter/docs/rules/recipe69.md b/linter/docs/rules/recipe69.md index 50d253b2ff54bfdc67412df656e6216b2917ef5f..80725b25c2840f4e39e3029f6947af2bfb57c3e8 100644 --- a/linter/docs/rules/recipe69.md +++ b/linter/docs/rules/recipe69.md @@ -34,11 +34,11 @@ using a temporary variable, where applicable) can be used for replacement. one = two two = tmp - let data: Number[] = [1,2,3,4] + let data: Number[] = [1, 2, 3, 4] let head = data[0] - let tail = new Number[data.length - 1] + let tail: Number[] = [] for (let i = 1; i < data.length; ++i) { - tail[i - 1] = data[i] + tail.push(data[i]) } ``` diff --git a/linter/docs/rules/recipe79.md b/linter/docs/rules/recipe79.md index 56ac1ea4fe71ac3ff98de23ffd33c202c6ef7458..15f916438120bd1e272a20cc4053f159675c80a6 100644 --- a/linter/docs/rules/recipe79.md +++ b/linter/docs/rules/recipe79.md @@ -17,7 +17,9 @@ be omitted. try { // some code } - catch (a: unknown) {} + catch (a: unknown) { + // handle error + } ``` @@ -29,7 +31,9 @@ be omitted. try { // some code } - catch (a) {} + catch (a) { + // handle error + } ``` diff --git a/linter/docs/rules/recipe8.md b/linter/docs/rules/recipe8.md index fd3e9e1004eb6050b4aff873026d39400e7bfc5b..32767236302c44ee45b242d7338080cbb8f75c20 100644 --- a/linter/docs/rules/recipe8.md +++ b/linter/docs/rules/recipe8.md @@ -1,6 +1,6 @@ # Use explicit types instead of ``any``, ``unknown`` -Rule ``arkts-no-any-undefined-unknown`` +Rule ``arkts-no-any-unknown`` **Severity: error** diff --git a/linter/docs/rules/recipe90.md b/linter/docs/rules/recipe90.md index 0613f6913d23d1eef21feed846cb1e9e10136829..2ef93392aa5625d59e0633641fabdb69460ef680 100644 --- a/linter/docs/rules/recipe90.md +++ b/linter/docs/rules/recipe90.md @@ -16,6 +16,7 @@ explicitly. ``` + // Compile-time error with noImplicitAny function f(x: number) { if (x <= 0) { return x @@ -23,6 +24,7 @@ explicitly. return g(x) } + // Compile-time error with noImplicitAny function g(x: number) { return f(x - 1) } diff --git a/linter/docs/rules/recipe93.md b/linter/docs/rules/recipe93.md index ceb0cacf5618c9c4847d9c33c0193ecda6c91a1d..ab4bce316abf01eaf8491b7d1c1d055c5ddd5527 100644 --- a/linter/docs/rules/recipe93.md +++ b/linter/docs/rules/recipe93.md @@ -14,7 +14,7 @@ ArkTS does not support the usage of ``this`` inside stand-alone functions. ``` function foo(i: number) { - this.count = i + this.count = i // Compile-time error only with noImplicitThis } class A { diff --git a/linter/src/CookBookMsg.ts b/linter/src/CookBookMsg.ts index 57e28c882afa5a3e0efa98ee3e4acb3ed57fbb53..50cf78a1b2bfdaec214ebe882ecbf34c20956a7b 100644 --- a/linter/src/CookBookMsg.ts +++ b/linter/src/CookBookMsg.ts @@ -27,7 +27,7 @@ cookBookTag[ 4 ] = 'Use unique names for types, namespaces, etc. (arkts-unique-n cookBookTag[ 5 ] = 'Use "let" instead of "var" (arkts-no-var)'; cookBookTag[ 6 ] = ''; cookBookTag[ 7 ] = ''; -cookBookTag[ 8 ] = 'Use explicit types instead of "any", "unknown" (arkts-no-any-undefined-unknown)'; +cookBookTag[ 8 ] = 'Use explicit types instead of "any", "unknown" (arkts-no-any-unknown)'; cookBookTag[ 9 ] = ''; cookBookTag[ 10 ] = '"bigint" is not a builtin type, suffix "n" for numeric literals is not supported (arkts-no-n-suffix)'; cookBookTag[ 11 ] = ''; @@ -75,14 +75,14 @@ cookBookTag[ 52 ] = 'Attempt to access an undefined property is a compile-time e cookBookTag[ 53 ] = 'Only "as T" syntax is supported for type casts (arkts-as-casts)'; cookBookTag[ 54 ] = 'JSX expressions are not supported (arkts-no-jsx)'; cookBookTag[ 55 ] = 'Unary operators "+", "-" and "~" work only on numbers (arkts-no-polymorphic-unops)'; -cookBookTag[ 56 ] = 'Unary "+" cannot be used for casting to "number" (arkts-no-unary-plus-cast)'; +cookBookTag[ 56 ] = ''; cookBookTag[ 57 ] = ''; cookBookTag[ 58 ] = ''; cookBookTag[ 59 ] = '"delete" operator is not supported (arkts-no-delete)'; cookBookTag[ 60 ] = '"typeof" operator is allowed only in expression contexts (arkts-no-type-query)'; -cookBookTag[ 61 ] = 'Binary operators "*", "/", "%", "-", "<<", ">>", ">>>", "&", "^" and "|" work only on numeric types (arkts-no-polymorphic-binops)'; +cookBookTag[ 61 ] = ''; cookBookTag[ 62 ] = ''; -cookBookTag[ 63 ] = 'Binary "+" operator supports implicit casts only for numbers and strings (arkts-no-polymorphic-plus)'; +cookBookTag[ 63 ] = ''; cookBookTag[ 64 ] = ''; cookBookTag[ 65 ] = '"instanceof" operator is partially supported (arkts-instanceof-ref-types)'; cookBookTag[ 66 ] = '"in" operator is not supported (arkts-no-in)'; @@ -134,7 +134,7 @@ cookBookTag[ 111 ] = 'Enumeration members can be initialized only with compile t cookBookTag[ 112 ] = ''; cookBookTag[ 113 ] = '"enum" declaration merging is not supported (arkts-no-enum-merging)'; cookBookTag[ 114 ] = 'Namespaces cannot be used as objects (arkts-no-ns-as-obj)'; -cookBookTag[ 115 ] = 'Scripts and modules (arkts-no-scripts)'; +cookBookTag[ 115 ] = ''; cookBookTag[ 116 ] = 'Non-declaration statements in namespaces are not supported (arkts-no-ns-statements)'; cookBookTag[ 117 ] = ''; cookBookTag[ 118 ] = 'Special import type declarations are not supported (arkts-no-special-imports)'; diff --git a/linter/src/TypeScriptLinter.ts b/linter/src/TypeScriptLinter.ts index 7db9b171b413484c310e178b148644e4009f9780..bfc3b80dcf9cc52bcf4af51c10eaea9d54f9b3dd 100644 --- a/linter/src/TypeScriptLinter.ts +++ b/linter/src/TypeScriptLinter.ts @@ -1428,6 +1428,12 @@ export class TypeScriptLinter { !this.tsUtils.relatedByInheritanceOrIdentical(targetType, exprType) ) this.incrementCounters(tsAsExpr, FaultID.StructuralIdentity); + // check for rule#65: 'number as Number' and 'boolean as Boolean' are disabled + if( + ( this.tsUtils.isNumberType(exprType) && targetType.getSymbol()?.getName() === 'Number' ) || + ( this.tsUtils.isBooleanType(exprType) && targetType.getSymbol()?.getName() === 'Boolean' ) + ) + this.incrementCounters(node, FaultID.TypeAssertion); } private handleTypeReference(node: ts.Node) { diff --git a/linter/test/instanceof.ts b/linter/test/instanceof.ts index 7f04b131b0decc7c28b286b74fdafa53ddd97a01..2289a2292c1ff992a31e34c8bc412a68d6d45b19 100644 --- a/linter/test/instanceof.ts +++ b/linter/test/instanceof.ts @@ -28,3 +28,13 @@ const e = (5.0 as number) instanceof Number; // false const f = (X | String) instanceof Object; const g = 3 instanceof Number; + + +let bad2Number = 5.0 as Number; +let pi = 3.14; +bad2Number = pi as Number; + +let bad2Boolean = true as Boolean; +let bad2Boolean = a as Boolean; + + diff --git a/linter/test/instanceof.ts.strict.json b/linter/test/instanceof.ts.strict.json index f9d548166e325ea9f11bd1b7a346c6e59aa69005..d95a4cf3335d3f034b90b9410f667a1c8f5e5263 100644 --- a/linter/test/instanceof.ts.strict.json +++ b/linter/test/instanceof.ts.strict.json @@ -33,6 +33,26 @@ "line": 30, "column": 11, "problem": "InstanceofUnsupported" + }, + { + "line": 33, + "column": 18, + "problem": "TypeAssertion" + }, + { + "line": 35, + "column": 14, + "problem": "TypeAssertion" + }, + { + "line": 37, + "column": 19, + "problem": "TypeAssertion" + }, + { + "line": 38, + "column": 19, + "problem": "TypeAssertion" } ] } \ No newline at end of file