1e41f4b71Sopenharmony_ci# ArkCompiler Subsystem Changelog 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## cl.ArkCompiler.1 TypeScript Syntax Check Change 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci**Access Level** 6e41f4b71Sopenharmony_ciOther 7e41f4b71Sopenharmony_ci 8e41f4b71Sopenharmony_ci**Reason for Change** 9e41f4b71Sopenharmony_ciThe TypeScript version in the OpenHarmony SDK is upgraded from 4.2.3 to 4.9.5. The new version supports more syntax features and provides higher type check capabilities. However, there are a few syntax features that are incompatible with earlier versions. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci**Change Occurrence Version** 12e41f4b71Sopenharmony_ciOpenHarmony SDK 4.1.3.1 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci**Change Impact** 15e41f4b71Sopenharmony_ciCompared with earlier versions, the syntax check in the new TypeScript version is stricter. It has 10 types of syntax features that are incompatible with the existing syntax. The following describes these syntax features and provides simple examples. 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci**Changed Syntax Features and Adaptation Guide** 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci1. Union enums cannot be compared to arbitrary numbers. 20e41f4b71Sopenharmony_ciEnums are considered union enums when their members are either automatically filled in, or trivially written. An enum of this type can recall each value that it potentially represents. 21e41f4b71Sopenharmony_ciThe following is an incorrect example: 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci ``` 24e41f4b71Sopenharmony_ci enum E { 25e41f4b71Sopenharmony_ci A = 0, 26e41f4b71Sopenharmony_ci B = 1, 27e41f4b71Sopenharmony_ci } 28e41f4b71Sopenharmony_ci function doSomething(x: E) { 29e41f4b71Sopenharmony_ci // Error! This condition will always return 'false' since the types 'E' and '-1' have no overlap. 30e41f4b71Sopenharmony_ci if (x === -1) { 31e41f4b71Sopenharmony_ci // ... 32e41f4b71Sopenharmony_ci } 33e41f4b71Sopenharmony_ci } 34e41f4b71Sopenharmony_ci ``` 35e41f4b71Sopenharmony_ci Adaptation suggestion: Use the **toString()** method to convert a number into a string for comparison. 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci2. More compliant indirect calls to imported functions. 38e41f4b71Sopenharmony_ci When an import from a non-ES module (such as the commonjs module in the FA model) is called, the **this** value is discarded, just as when an import from an ES module is called. 39e41f4b71Sopenharmony_ci The following example shows the change: 40e41f4b71Sopenharmony_ci ``` 41e41f4b71Sopenharmony_ci // Assume that this is the imported module, which has a 'foo' and 'feature' export. 42e41f4b71Sopenharmony_ci let fooModule = { 43e41f4b71Sopenharmony_ci foo() { 44e41f4b71Sopenharmony_ci console.log(this); 45e41f4b71Sopenharmony_ci }, 46e41f4b71Sopenharmony_ci feature: 'oh' 47e41f4b71Sopenharmony_ci }; 48e41f4b71Sopenharmony_ci 49e41f4b71Sopenharmony_ci // Behavior before the change: 50e41f4b71Sopenharmony_ci fooModule.foo(); // Output: {"feature": "oh"} 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ci // Behavior after the change (in effect, '(0, fooModule.foo) is called, which is slightly different from the preceding behavior): 53e41f4b71Sopenharmony_ci (0, fooModule.foo)(); // Output: undefined 54e41f4b71Sopenharmony_ci ``` 55e41f4b71Sopenharmony_ci3. Abstract properties do not allow initializers. 56e41f4b71Sopenharmony_ciThe following code will report an error because abstract properties are not allowed have initializers: 57e41f4b71Sopenharmony_ci ``` 58e41f4b71Sopenharmony_ci abstract class C { 59e41f4b71Sopenharmony_ci abstract prop = 1; 60e41f4b71Sopenharmony_ci // ~~~~ 61e41f4b71Sopenharmony_ci // Property 'prop' cannot have an initializer because it is marked abstract. 62e41f4b71Sopenharmony_ci } 63e41f4b71Sopenharmony_ci ``` 64e41f4b71Sopenharmony_ci Adaptation suggestion: Delete the initializer. 65e41f4b71Sopenharmony_ci4. The rest parameter syntax deletes unexpandable members from generic objects. 66e41f4b71Sopenharmony_ciWhen being deconstructed from generic objects, properties are regarded as all deconstructible in earlier versions. In the new version, they are strictly analyzed to find out whether they can be deconstructed. Properties that should not be deconstructed include private properties, private methods, and static properties. The following code will report an error: 67e41f4b71Sopenharmony_ci ``` 68e41f4b71Sopenharmony_ci class Thing { 69e41f4b71Sopenharmony_ci someProperty = 42; 70e41f4b71Sopenharmony_ci someMethod() { 71e41f4b71Sopenharmony_ci // ... 72e41f4b71Sopenharmony_ci } 73e41f4b71Sopenharmony_ci } 74e41f4b71Sopenharmony_ci function foo<T extends Thing>(x: T) { 75e41f4b71Sopenharmony_ci let { someProperty, ...rest } = x; 76e41f4b71Sopenharmony_ci // Used to work, is now an error! 77e41f4b71Sopenharmony_ci // Property 'someMethod' does not exist on type 'Omit<T, "someProperty" | "someMethod">'. 78e41f4b71Sopenharmony_ci rest.someMethod(); 79e41f4b71Sopenharmony_ci } 80e41f4b71Sopenharmony_ci ``` 81e41f4b71Sopenharmony_ci Adaptation suggestion: When deconstructing a property from a generic object, make sure it can be deconstructed. 82e41f4b71Sopenharmony_ci5. There are stricter checks with template string expressions. 83e41f4b71Sopenharmony_ciIf a symbol value is used in JavaScript, both JavaScript and TypeScript will throw an error. However, TypeScript now checks whether a generic value contained in a symbol is used in the template string. 84e41f4b71Sopenharmony_ci ``` 85e41f4b71Sopenharmony_ci function logKey<S extends string | symbol>(key: S): S { 86e41f4b71Sopenharmony_ci // Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. 87e41f4b71Sopenharmony_ci console.log(`${key} is the key`); 88e41f4b71Sopenharmony_ci return key; 89e41f4b71Sopenharmony_ci } 90e41f4b71Sopenharmony_ci ``` 91e41f4b71Sopenharmony_ci Adaptation suggestion: Wrap the expression in **'String(...)'**. 92e41f4b71Sopenharmony_ci6. Read-only tuples have a read-only length property. 93e41f4b71Sopenharmony_ci The read-only tuple now treats the length property as read-only. This can be seen for tuples with optional trailing and rest element types. 94e41f4b71Sopenharmony_ci ``` 95e41f4b71Sopenharmony_ci function overwriteLength(tuple: readonly [string, string, string]) { 96e41f4b71Sopenharmony_ci // Now errors. 97e41f4b71Sopenharmony_ci tuple.length = 7; 98e41f4b71Sopenharmony_ci } 99e41f4b71Sopenharmony_ci ``` 100e41f4b71Sopenharmony_ci7. Objects cannot be compared with array literals. 101e41f4b71Sopenharmony_ciValue-comparison operations '==' and '===' between objects (and arrays) in JavaScript check whether two references point to the same value. Now the following code will report an error: 102e41f4b71Sopenharmony_ci ``` 103e41f4b71Sopenharmony_ci if (peopleAtHome === []) { 104e41f4b71Sopenharmony_ci // ~~~~~~~~~~~~~~~~~~~ 105e41f4b71Sopenharmony_ci // This condition will always return 'false' since JavaScript compares objects by reference, not value. 106e41f4b71Sopenharmony_ci console.log("here's where I lie, broken inside. </3") 107e41f4b71Sopenharmony_ci adoptAnimals(); 108e41f4b71Sopenharmony_ci } 109e41f4b71Sopenharmony_ci ``` 110e41f4b71Sopenharmony_ci8. Unused renames are not allowed in type signatures. 111e41f4b71Sopenharmony_ciIn the following example, you might think that **makePerson** takes an object with a **name** property of the string type and an **age** property of the number type. However, the destructuring syntax is actually taking precedence here. **makePerson** renames **name** and **age** to **string** and **number** respectively. 112e41f4b71Sopenharmony_ci ``` 113e41f4b71Sopenharmony_ci declare function makePerson({ name: string, age: number }): Person; 114e41f4b71Sopenharmony_ci ``` 115e41f4b71Sopenharmony_ci The correct way to write the above signature is as follows: 116e41f4b71Sopenharmony_ci ``` 117e41f4b71Sopenharmony_ci declare function makePerson(options: { name: string, age: number }): Person; 118e41f4b71Sopenharmony_ci // or 119e41f4b71Sopenharmony_ci declare function makePerson({ name, age }: { name: string, age: number }): Person; 120e41f4b71Sopenharmony_ci ``` 121e41f4b71Sopenharmony_ci9. Checks for equality on NaN. 122e41f4b71Sopenharmony_ciAn error will be reported on direct comparisons against NaN. 123e41f4b71Sopenharmony_ci ``` 124e41f4b71Sopenharmony_ci function validate(someValue: number) { 125e41f4b71Sopenharmony_ci return someValue !== NaN; 126e41f4b71Sopenharmony_ci // ~~~~~~~~~~~~~~~~~ 127e41f4b71Sopenharmony_ci // error: This condition will always return 'true'. Did you mean '!Number.isNaN(someValue)'? 128e41f4b71Sopenharmony_ci } 129e41f4b71Sopenharmony_ci ``` 130e41f4b71Sopenharmony_ci Adaptation suggestion: Use **Number.isNaN** instead. 131e41f4b71Sopenharmony_ci10. Errors caused by enhanced type inference and check capabilities 132e41f4b71Sopenharmony_ciAfter TypeScript is upgraded to 4.9.5, its type inference and check capabilities are enhanced, and syntax errors other than those described above may be detected. Correcting these syntax errors help improve run-time performance. 133