1/* 2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16let obj = {n: 42, s: 'foo'} // OK in TypeScript, CTE in ArkTS: unknown type of obj. 17 18class C { 19 n: number = 0; 20 s: string = ""; 21} 22 23let c1: C = {n: 42, s: 'foo'} // Declaration + initialization: type of the literla is inferred from the type of c1. 24 25let c2: C; 26c2 = {n: 42, s: 'foo'}; // Initialization after declaration: type of the literal is inferred from the type of c2. 27 28let c3: Object = {n: 42, s: 'foo'} as C as Object; // Type of the literal is inferred from the 'as' cast. 29console.log(c3 instanceof C); // NB! Output is true in ArkTS, but is false in TS. 30 31function foo(c: C) { 32 console.log('foo is called'); 33} 34 35foo({n: 42, s: 'foo'}); // Parsing as an argument: type of the literal is inferred from the type of parameter 'c' 36 37function bar(): C { 38 return {n: 42, s: 'foo'}; // Returning from function: type of the literal is inferred from the bar's return type. 39} 40 41let cc: C[] = [{n: 1, s: '1'}, {n: 2, s: '2'}]; // Type of the literal is inferred from the type of the array. 42 43class D { 44 b: boolean = false; 45 c: C = {n: 0, s: ""}; 46} 47 48let d: D = { 49 b: true, 50 c: { // Initialization of a field with a literal: type of the literal is inferred from the definition of class D. 51 n: 42, 52 s: 'foo' 53 } 54} 55 56// Restrictions of classes that can be initialized with literal 57// Default initializable class. 58class C1 { 59 n: number = 0; 60 s?: string; 61} 62 63let c4: C1 = {n: 42}; // OK in TS, OK in ArkTS, c.s is null 64 65class C2 { 66 s: string; 67 constructor(s: string) { 68 this.s = "s = " + s; 69 } 70} 71 72let c5: C2 = {s: 'foo'} // OK in TS, CTE in ArkTS 73 74// All class fields are accessible at the point of initialization. 75class C3 { 76 private n: number = 0; 77 public s: string = ''; 78} 79 80// CTE in TypeScript, CTE in ArkTS // let c6: C3 = {n: 42, s: 'foo'}, 81 82class C4 { 83 readonly n: number = 0; 84 readonly s: string = ''; 85} 86 87let c7: C4 = {n: 42, s: 'foo'}; // OK in TS, CTE in ArkTS 88 89// Class is non-abstract 90abstract class A {} 91let a: A = {}; // OK in TS, CTE in ArkTS 92 93// Class declares no methods, apart from optionally declared constructors and setters. 94class C5 { 95 n: number = 0; 96 s: string = ''; 97 f() { 98 console.log('C5.f is called'); 99 } 100} 101 102let c8: C5 = {n: 42, s: 'foo', f: () => {}} // OK in TS, CTE in ArkTS 103 104// NB! If a class has getters/setters the semantics of initialization differs: 105class C6 { 106 n: number = 0; 107 _s: string = ''; 108 get s(): string { return this._s; } 109 set s(s: string) { this._s = s; } 110} 111 112let c9: C6 = {n: 42, _s: 'foo', s: 'bar'} 113console.log(c9.s); // TS: 'bar', ArkTS: 'bar' 114console.log(c9._s); // TS: 'foo', ArkTS: 'bar' 115 116// Extra fields are not allowed (eventually it means that it's not possible to assign literals to Object / object): 117class C7 { 118 n: number = 0; 119 s: string = ''; 120} 121// TS: CTE, ArtTS: CTE // let c10: C7 = {n: 42, s: '', extra: true}, 122let o1: Object = {s: '', n: 42} // OK in TS, CTE in ArkTS: no fields 'n' and 's' in Object 123let o2: object = {n: 42, s: ''} // OK in TS, CTE in ArkTS: no fields 'n' and 's' in object 124 125// If initialized class is inherited from another class, the base class must also be literal-initializable, 126// and initialization should happen from the 'glattened' literal: 127class Base { 128 n: number = 0; 129} 130 131class Derived extends Base { 132 s: string = ''; 133} 134 135let d2: Derived = {n: 42, s: ''}; 136 137// Interface should not declare methods, only properties are allowed. 138interface I { 139 n: number; 140 s: string; 141 f(): void; 142} 143 144let i: I = {n: 42, s: '', f: () => {console.log('I.f is called')}} // OK in TypeScript, CTE in ArkTS 145 146// Interface properties of reference types must be default-initializable: 147interface I2 { 148 n: number; 149 s: string; // Assuming that 'string' is an alias for 'String', and there is String() constructor (what is true). 150} 151 152let i2: I2 = {n: 42, s: ''}; 153 154interface CompilerOptions { 155 strict?: boolean; 156 sourcePath?: string; 157 targetPath?: string; 158} 159 160const options: CompilerOptions = { // OK, as 'targetPath' field is optional 161 strict: true, 162 sourcePath: './src', 163}; 164 165// Function parameter with union type. 166function funcWithUnionParam(x: C | number): void { } 167funcWithUnionParam({ n: 1, s: '2' }) // OK, union type is supported 168 169// issue 13022: property with union type 170class UnionProperty { 171 a: number | string = 123; 172 b?: boolean | number; 173} 174let u: UnionProperty = { a: 1 }; // OK, union type is supported 175u = { a: '2' }; // OK, union type is supported 176u = { a: 3, b: true }; // OK, union type is supported 177 178// issue 13022: optional property 179class OptionalProp { 180 a?: number; 181} 182let o: OptionalProp = {}; 183o = {a: 1}; // OK 184 185class OptionalProp2 { 186 a?: number; 187 b: string; 188} 189function optProp(a: OptionalProp2) {} 190optProp({b: ''}); // OK 191optProp({a: 0, b: '1'}); // OK 192 193// Property with inheritance 194class E1 { 195 x: number; 196 y: Base; 197} 198let e1 : E1 = { 199 x: 1, 200 y: new Derived() 201} 202 203// Property with inheritance through generic type parameter 204class E2<T> { 205 x: number; 206 y: T; 207} 208let e2 : E2<Base> = { 209 x: 1, 210 y: new Derived() 211} 212 213// Type alias chain to interface 214interface ITypeAlias<T> { a: number; b: T } 215type ITA<T> = ITypeAlias<T>; 216type ITA2<K> = ITA<K>; 217let ti: ITA2<string> = { // OK, 'ITA2' is an alias to interface 'ITypeAlias' 218 a: 12, 219 b: '34' 220} 221 222// Type alias chain to class 223class CTypeAlias<T> { 224 a: number; 225 b: T; 226} 227type CTA<T> = CTypeAlias<T>; 228type CTA2<K> = CTA<K>; 229let tc: CTA2<string> = { // OK, 'CTA' is an alias to class 'CTypeAlias' 230 a: 4, 231 b: '4' 232} 233 234// issue 13114: Const enum value converted to string/number type. 235const enum ATTRIBUTE { 236 ROW = 'Row', 237 COLUMN = 'Column', 238 COLUMN_REVERSE = 'ColumnReverse', 239}; 240const enum GROUP { 241 MAIN_DIRECTION = 'MAIN_DIRECTION', 242}; 243enum Orientation { 244 Horizontal, 245 Vertical 246} 247class ContainerModuleItem { 248 groupName: string = ''; 249 attributeList: string[] = []; 250 attribute: ATTRIBUTE = ATTRIBUTE.COLUMN; 251 orientation: number = 0; 252} 253const FLEX_MODULE: ContainerModuleItem[] = [ 254 { 255 groupName: GROUP.MAIN_DIRECTION, 256 attributeList: [ATTRIBUTE.COLUMN, ATTRIBUTE.ROW, ATTRIBUTE.COLUMN_REVERSE], 257 attribute: ATTRIBUTE.ROW, 258 orientation: Orientation.Horizontal 259 } 260]; 261 262interface I3 {} 263 264class CCl implements I3 {} 265 266class CCl2 extends CCl implements I3 {} 267 268interface I4 { 269 a: I3; 270 b: I3; 271 c: CCl; 272 d: CCl2; 273} 274 275class DCl { 276 constructor(a: I4) {} 277} 278 279let c: I4 = {a: new CCl(), b: new CCl2(), c: new CCl2(), d: new CCl2()} 280 281new DCl({a: new CCl(), b: new CCl2(), c: new CCl2(), d: new CCl2()}) 282 283let oo1: Object = {} 284 285let oo2: Object = {a: 12} 286