Reorganize skill files into skills/ subdirectory
This commit is contained in:
@@ -1,57 +1,57 @@
|
|||||||
// ArkTS Basic Component Template
|
// ArkTS Basic Component Template
|
||||||
// Replace {{ComponentName}} with your component name
|
// Replace {{ComponentName}} with your component name
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
@Component
|
@Component
|
||||||
struct {{ComponentName}} {
|
struct {{ComponentName}} {
|
||||||
// State management
|
// State management
|
||||||
@State isLoading: boolean = false;
|
@State isLoading: boolean = false;
|
||||||
@State errorMessage: string = '';
|
@State errorMessage: string = '';
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
this.loadData();
|
this.loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToDisappear(): void {
|
aboutToDisappear(): void {
|
||||||
// Cleanup resources
|
// Cleanup resources
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
async loadData(): Promise<void> {
|
async loadData(): Promise<void> {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
try {
|
try {
|
||||||
// Load data here
|
// Load data here
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.errorMessage = 'Failed to load data';
|
this.errorMessage = 'Failed to load data';
|
||||||
} finally {
|
} finally {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build
|
// Build
|
||||||
build() {
|
build() {
|
||||||
Column() {
|
Column() {
|
||||||
if (this.isLoading) {
|
if (this.isLoading) {
|
||||||
LoadingProgress()
|
LoadingProgress()
|
||||||
.width(50)
|
.width(50)
|
||||||
.height(50)
|
.height(50)
|
||||||
} else if (this.errorMessage) {
|
} else if (this.errorMessage) {
|
||||||
Text(this.errorMessage)
|
Text(this.errorMessage)
|
||||||
.fontSize(16)
|
.fontSize(16)
|
||||||
.fontColor(Color.Red)
|
.fontColor(Color.Red)
|
||||||
Button('Retry')
|
Button('Retry')
|
||||||
.onClick(() => { this.loadData(); })
|
.onClick(() => { this.loadData(); })
|
||||||
} else {
|
} else {
|
||||||
// Main content here
|
// Main content here
|
||||||
Text('{{ComponentName}}')
|
Text('{{ComponentName}}')
|
||||||
.fontSize(24)
|
.fontSize(24)
|
||||||
.fontWeight(FontWeight.Bold)
|
.fontWeight(FontWeight.Bold)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height('100%')
|
.height('100%')
|
||||||
.justifyContent(FlexAlign.Center)
|
.justifyContent(FlexAlign.Center)
|
||||||
.alignItems(HorizontalAlign.Center)
|
.alignItems(HorizontalAlign.Center)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,129 +1,129 @@
|
|||||||
// ArkTS List Page Template
|
// ArkTS List Page Template
|
||||||
// Replace {{PageName}}, {{ItemType}}, {{itemName}} with your values
|
// Replace {{PageName}}, {{ItemType}}, {{itemName}} with your values
|
||||||
|
|
||||||
import { router } from '@kit.ArkUI';
|
import { router } from '@kit.ArkUI';
|
||||||
|
|
||||||
interface {{ItemType}} {
|
interface {{ItemType}} {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
@Component
|
@Component
|
||||||
struct {{PageName}} {
|
struct {{PageName}} {
|
||||||
@State items: {{ItemType}}[] = [];
|
@State items: {{ItemType}}[] = [];
|
||||||
@State isLoading: boolean = false;
|
@State isLoading: boolean = false;
|
||||||
@State isRefreshing: boolean = false;
|
@State isRefreshing: boolean = false;
|
||||||
|
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
this.loadItems();
|
this.loadItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadItems(): Promise<void> {
|
async loadItems(): Promise<void> {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
try {
|
try {
|
||||||
// TODO: Fetch items from API
|
// TODO: Fetch items from API
|
||||||
this.items = [
|
this.items = [
|
||||||
{ id: '1', title: 'Item 1', description: 'Description 1' },
|
{ id: '1', title: 'Item 1', description: 'Description 1' },
|
||||||
{ id: '2', title: 'Item 2', description: 'Description 2' },
|
{ id: '2', title: 'Item 2', description: 'Description 2' },
|
||||||
];
|
];
|
||||||
} finally {
|
} finally {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshItems(): Promise<void> {
|
async refreshItems(): Promise<void> {
|
||||||
this.isRefreshing = true;
|
this.isRefreshing = true;
|
||||||
await this.loadItems();
|
await this.loadItems();
|
||||||
this.isRefreshing = false;
|
this.isRefreshing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateToDetail(item: {{ItemType}}): void {
|
navigateToDetail(item: {{ItemType}}): void {
|
||||||
router.pushUrl({
|
router.pushUrl({
|
||||||
url: 'pages/{{PageName}}Detail',
|
url: 'pages/{{PageName}}Detail',
|
||||||
params: { id: item.id }
|
params: { id: item.id }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
ItemCard(item: {{ItemType}}) {
|
ItemCard(item: {{ItemType}}) {
|
||||||
Column() {
|
Column() {
|
||||||
Text(item.title)
|
Text(item.title)
|
||||||
.fontSize(18)
|
.fontSize(18)
|
||||||
.fontWeight(FontWeight.Medium)
|
.fontWeight(FontWeight.Medium)
|
||||||
.fontColor('#333333')
|
.fontColor('#333333')
|
||||||
|
|
||||||
Text(item.description)
|
Text(item.description)
|
||||||
.fontSize(14)
|
.fontSize(14)
|
||||||
.fontColor('#666666')
|
.fontColor('#666666')
|
||||||
.margin({ top: 4 })
|
.margin({ top: 4 })
|
||||||
}
|
}
|
||||||
.alignItems(HorizontalAlign.Start)
|
.alignItems(HorizontalAlign.Start)
|
||||||
.padding(16)
|
.padding(16)
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.backgroundColor(Color.White)
|
.backgroundColor(Color.White)
|
||||||
.borderRadius(8)
|
.borderRadius(8)
|
||||||
.onClick(() => { this.navigateToDetail(item); })
|
.onClick(() => { this.navigateToDetail(item); })
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
Column() {
|
Column() {
|
||||||
// Header
|
// Header
|
||||||
Row() {
|
Row() {
|
||||||
Text('{{PageName}}')
|
Text('{{PageName}}')
|
||||||
.fontSize(24)
|
.fontSize(24)
|
||||||
.fontWeight(FontWeight.Bold)
|
.fontWeight(FontWeight.Bold)
|
||||||
|
|
||||||
Blank()
|
Blank()
|
||||||
|
|
||||||
Button('Add')
|
Button('Add')
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
router.pushUrl({ url: 'pages/{{PageName}}Create' });
|
router.pushUrl({ url: 'pages/{{PageName}}Create' });
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.padding(16)
|
.padding(16)
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
if (this.isLoading && this.items.length === 0) {
|
if (this.isLoading && this.items.length === 0) {
|
||||||
Column() {
|
Column() {
|
||||||
LoadingProgress().width(50).height(50)
|
LoadingProgress().width(50).height(50)
|
||||||
Text('Loading...').margin({ top: 16 })
|
Text('Loading...').margin({ top: 16 })
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.layoutWeight(1)
|
.layoutWeight(1)
|
||||||
.justifyContent(FlexAlign.Center)
|
.justifyContent(FlexAlign.Center)
|
||||||
} else if (this.items.length === 0) {
|
} else if (this.items.length === 0) {
|
||||||
Column() {
|
Column() {
|
||||||
Text('No items found')
|
Text('No items found')
|
||||||
.fontSize(16)
|
.fontSize(16)
|
||||||
.fontColor('#999999')
|
.fontColor('#999999')
|
||||||
Button('Refresh')
|
Button('Refresh')
|
||||||
.margin({ top: 16 })
|
.margin({ top: 16 })
|
||||||
.onClick(() => { this.loadItems(); })
|
.onClick(() => { this.loadItems(); })
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.layoutWeight(1)
|
.layoutWeight(1)
|
||||||
.justifyContent(FlexAlign.Center)
|
.justifyContent(FlexAlign.Center)
|
||||||
} else {
|
} else {
|
||||||
Refresh({ refreshing: $$this.isRefreshing }) {
|
Refresh({ refreshing: $$this.isRefreshing }) {
|
||||||
List({ space: 12 }) {
|
List({ space: 12 }) {
|
||||||
ForEach(this.items, (item: {{ItemType}}) => {
|
ForEach(this.items, (item: {{ItemType}}) => {
|
||||||
ListItem() {
|
ListItem() {
|
||||||
this.ItemCard(item)
|
this.ItemCard(item)
|
||||||
}
|
}
|
||||||
}, (item: {{ItemType}}) => item.id)
|
}, (item: {{ItemType}}) => item.id)
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.padding({ left: 16, right: 16 })
|
.padding({ left: 16, right: 16 })
|
||||||
}
|
}
|
||||||
.onRefreshing(() => { this.refreshItems(); })
|
.onRefreshing(() => { this.refreshItems(); })
|
||||||
.layoutWeight(1)
|
.layoutWeight(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height('100%')
|
.height('100%')
|
||||||
.backgroundColor('#f5f5f5')
|
.backgroundColor('#f5f5f5')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
126
skills/arkts-development/references/arkguard-obfuscation.md
Normal file
126
skills/arkts-development/references/arkguard-obfuscation.md
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# ArkGuard 代码混淆指南
|
||||||
|
|
||||||
|
ArkGuard 是 HarmonyOS 官方推荐的代码混淆工具,用于提升应用安全性,防止逆向分析。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
- **DevEco Studio**: 5.0.3.600 及以上版本
|
||||||
|
- **项目模型**: 仅支持 Stage 模型
|
||||||
|
- **生效模式**: 仅在 Release 模式下生效
|
||||||
|
|
||||||
|
## 开启混淆
|
||||||
|
|
||||||
|
在模块的 `build-profile.json5` 中配置:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"arkOptions": {
|
||||||
|
"obfuscation": {
|
||||||
|
"ruleOptions": {
|
||||||
|
"enable": true,
|
||||||
|
"files": ["./obfuscation-rules.txt"]
|
||||||
|
},
|
||||||
|
"consumerFiles": ["./consumer-rules.txt"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 混淆规则配置
|
||||||
|
|
||||||
|
在项目根目录创建 `obfuscation-rules.txt`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
# 开启属性混淆
|
||||||
|
-enable-property-obfuscation
|
||||||
|
|
||||||
|
# 开启顶层作用域名称混淆
|
||||||
|
-enable-toplevel-obfuscation
|
||||||
|
|
||||||
|
# 开启文件名混淆
|
||||||
|
-enable-filename-obfuscation
|
||||||
|
|
||||||
|
# 开启导入导出名称混淆
|
||||||
|
-enable-export-obfuscation
|
||||||
|
```
|
||||||
|
|
||||||
|
## 白名单配置
|
||||||
|
|
||||||
|
某些名称不能混淆(如动态属性名、API 字段、数据库字段等):
|
||||||
|
|
||||||
|
```text
|
||||||
|
# 保留属性名
|
||||||
|
-keep-property-name apiKey
|
||||||
|
-keep-property-name userId
|
||||||
|
-keep-property-name responseData
|
||||||
|
|
||||||
|
# 保留全局名称
|
||||||
|
-keep-global-name AppConfig
|
||||||
|
|
||||||
|
# 保留文件名
|
||||||
|
-keep-file-name MainPage
|
||||||
|
-keep-file-name LoginPage
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置文件说明
|
||||||
|
|
||||||
|
| 配置文件 | 作用 | 可修改 | 影响范围 |
|
||||||
|
|---------|------|:------:|---------|
|
||||||
|
| `obfuscation-rules.txt` | 本模块编译时的混淆规则 | ✓ | 本模块 |
|
||||||
|
| `consumer-rules.txt` | 本模块被依赖时的混淆规则(建议仅配置保留项) | ✓ | 依赖此模块的模块 |
|
||||||
|
| `obfuscation.txt` | HAR/HSP 构建产物,自动生成 | ✗ | 依赖模块 |
|
||||||
|
|
||||||
|
## 常用混淆选项
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `-enable-property-obfuscation` | 混淆对象属性名 |
|
||||||
|
| `-enable-toplevel-obfuscation` | 混淆顶层作用域的变量和函数名 |
|
||||||
|
| `-enable-filename-obfuscation` | 混淆文件名 |
|
||||||
|
| `-enable-export-obfuscation` | 混淆导入导出的名称 |
|
||||||
|
| `-disable-obfuscation` | 临时禁用混淆(用于调试) |
|
||||||
|
|
||||||
|
## 白名单选项
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `-keep-property-name <name>` | 保留指定属性名不被混淆 |
|
||||||
|
| `-keep-global-name <name>` | 保留指定全局名称不被混淆 |
|
||||||
|
| `-keep-file-name <name>` | 保留指定文件名不被混淆 |
|
||||||
|
|
||||||
|
## 问题排查
|
||||||
|
|
||||||
|
### 排查步骤
|
||||||
|
|
||||||
|
1. **确认是否与混淆相关**: 临时添加 `-disable-obfuscation` 禁用混淆,验证问题是否消失
|
||||||
|
2. **定位问题字段**: 根据崩溃日志定位被混淆的关键字段
|
||||||
|
3. **添加白名单**: 将问题字段加入 `-keep-property-name` 白名单
|
||||||
|
|
||||||
|
### 常见需要保留的场景
|
||||||
|
|
||||||
|
- **网络请求**: 接口传参字段名、响应数据字段名
|
||||||
|
- **数据库操作**: 表字段名
|
||||||
|
- **系统 API**: 系统回调参数
|
||||||
|
- **三方库接口**: 三方库要求的字段名
|
||||||
|
|
||||||
|
### 示例:网络请求字段保留
|
||||||
|
|
||||||
|
```text
|
||||||
|
# API 请求/响应字段
|
||||||
|
-keep-property-name code
|
||||||
|
-keep-property-name message
|
||||||
|
-keep-property-name data
|
||||||
|
-keep-property-name token
|
||||||
|
-keep-property-name userId
|
||||||
|
```
|
||||||
|
|
||||||
|
## 验证混淆效果
|
||||||
|
|
||||||
|
1. 切换到 **Release** 模式编译
|
||||||
|
2. 检查构建产物
|
||||||
|
3. 使用反编译工具验证类名/方法名/属性名是否已混淆
|
||||||
|
4. 测试应用功能是否正常
|
||||||
|
|
||||||
|
## 参考
|
||||||
|
|
||||||
|
- [华为官方文档 - ArkGuard](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-arkguard)
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,407 +1,407 @@
|
|||||||
# TypeScript to ArkTS Migration Guide
|
# TypeScript to ArkTS Migration Guide
|
||||||
|
|
||||||
Complete guide for migrating TypeScript code to ArkTS, covering all language constraints and adaptation rules.
|
Complete guide for migrating TypeScript code to ArkTS, covering all language constraints and adaptation rules.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
1. [Overview](#overview)
|
1. [Overview](#overview)
|
||||||
2. [Constraint Categories](#constraint-categories)
|
2. [Constraint Categories](#constraint-categories)
|
||||||
3. [Prohibited Features](#prohibited-features)
|
3. [Prohibited Features](#prohibited-features)
|
||||||
4. [Migration Examples](#migration-examples)
|
4. [Migration Examples](#migration-examples)
|
||||||
5. [Migration Checklist](#migration-checklist)
|
5. [Migration Checklist](#migration-checklist)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
ArkTS is based on TypeScript but enforces stricter rules for:
|
ArkTS is based on TypeScript but enforces stricter rules for:
|
||||||
- **Performance**: Static analysis enables AOT compilation
|
- **Performance**: Static analysis enables AOT compilation
|
||||||
- **Type Safety**: Eliminates runtime type errors
|
- **Type Safety**: Eliminates runtime type errors
|
||||||
- **Predictability**: Fixed object structures at compile time
|
- **Predictability**: Fixed object structures at compile time
|
||||||
|
|
||||||
Constraints are categorized as:
|
Constraints are categorized as:
|
||||||
- **Error**: Must fix, blocks compilation
|
- **Error**: Must fix, blocks compilation
|
||||||
- **Warning**: Should fix, may become errors in future
|
- **Warning**: Should fix, may become errors in future
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Constraint Categories
|
## Constraint Categories
|
||||||
|
|
||||||
### 1. Type System Constraints
|
### 1. Type System Constraints
|
||||||
|
|
||||||
#### Prohibited: `any` and `unknown`
|
#### Prohibited: `any` and `unknown`
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
let value: any = getData();
|
let value: any = getData();
|
||||||
let result: unknown = parse(input);
|
let result: unknown = parse(input);
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
interface Data { id: number; name: string; }
|
interface Data { id: number; name: string; }
|
||||||
let value: Data = getData();
|
let value: Data = getData();
|
||||||
let result: Data | null = parse(input);
|
let result: Data | null = parse(input);
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Prohibited: Type assertions to `any`
|
#### Prohibited: Type assertions to `any`
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
(obj as any).dynamicProp = value;
|
(obj as any).dynamicProp = value;
|
||||||
|
|
||||||
// ✅ ArkTS - Define complete interface
|
// ✅ ArkTS - Define complete interface
|
||||||
interface MyObject {
|
interface MyObject {
|
||||||
existingProp: string;
|
existingProp: string;
|
||||||
dynamicProp?: number;
|
dynamicProp?: number;
|
||||||
}
|
}
|
||||||
let obj: MyObject = { existingProp: 'test' };
|
let obj: MyObject = { existingProp: 'test' };
|
||||||
obj.dynamicProp = value;
|
obj.dynamicProp = value;
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Variable Declaration
|
### 2. Variable Declaration
|
||||||
|
|
||||||
#### Prohibited: `var`
|
#### Prohibited: `var`
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
var count = 0;
|
var count = 0;
|
||||||
var name = "hello";
|
var name = "hello";
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const name = "hello";
|
const name = "hello";
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Object Structure Constraints
|
### 3. Object Structure Constraints
|
||||||
|
|
||||||
#### Prohibited: Runtime property modification
|
#### Prohibited: Runtime property modification
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class Point {
|
class Point {
|
||||||
x: number = 0;
|
x: number = 0;
|
||||||
y: number = 0;
|
y: number = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = new Point();
|
let p = new Point();
|
||||||
|
|
||||||
// ❌ All prohibited
|
// ❌ All prohibited
|
||||||
p['z'] = 99; // Dynamic property
|
p['z'] = 99; // Dynamic property
|
||||||
delete p.x; // Property deletion
|
delete p.x; // Property deletion
|
||||||
Object.assign(p, {z: 1}); // Runtime extension
|
Object.assign(p, {z: 1}); // Runtime extension
|
||||||
|
|
||||||
// ✅ Define all properties upfront
|
// ✅ Define all properties upfront
|
||||||
class Point3D {
|
class Point3D {
|
||||||
x: number = 0;
|
x: number = 0;
|
||||||
y: number = 0;
|
y: number = 0;
|
||||||
z: number = 0;
|
z: number = 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Prohibited: Structural typing (duck typing)
|
#### Prohibited: Structural typing (duck typing)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface Named { name: string; }
|
interface Named { name: string; }
|
||||||
|
|
||||||
// ❌ TypeScript allows structural matching
|
// ❌ TypeScript allows structural matching
|
||||||
let obj = { name: "Alice", age: 25 };
|
let obj = { name: "Alice", age: 25 };
|
||||||
let named: Named = obj; // Works in TS, fails in ArkTS
|
let named: Named = obj; // Works in TS, fails in ArkTS
|
||||||
|
|
||||||
// ✅ ArkTS requires explicit implementation
|
// ✅ ArkTS requires explicit implementation
|
||||||
class Person implements Named {
|
class Person implements Named {
|
||||||
name: string = "";
|
name: string = "";
|
||||||
age: number = 0;
|
age: number = 0;
|
||||||
}
|
}
|
||||||
let named: Named = new Person();
|
let named: Named = new Person();
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Private Fields
|
### 4. Private Fields
|
||||||
|
|
||||||
#### Prohibited: `#` private fields
|
#### Prohibited: `#` private fields
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
class MyClass {
|
class MyClass {
|
||||||
#secret: string = "";
|
#secret: string = "";
|
||||||
#getValue(): string { return this.#secret; }
|
#getValue(): string { return this.#secret; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
class MyClass {
|
class MyClass {
|
||||||
private secret: string = "";
|
private secret: string = "";
|
||||||
private getValue(): string { return this.secret; }
|
private getValue(): string { return this.secret; }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Symbol Properties
|
### 5. Symbol Properties
|
||||||
|
|
||||||
#### Prohibited: Symbol as property key
|
#### Prohibited: Symbol as property key
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
const sym = Symbol('key');
|
const sym = Symbol('key');
|
||||||
let obj = { [sym]: 'value' };
|
let obj = { [sym]: 'value' };
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
let obj = { key: 'value' };
|
let obj = { key: 'value' };
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Prohibited Statements
|
### 6. Prohibited Statements
|
||||||
|
|
||||||
#### `for...in`
|
#### `for...in`
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
for (let key in obj) {
|
for (let key in obj) {
|
||||||
console.log(obj[key]);
|
console.log(obj[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS - Use Object.keys with forEach
|
// ✅ ArkTS - Use Object.keys with forEach
|
||||||
Object.keys(obj).forEach((key: string) => {
|
Object.keys(obj).forEach((key: string) => {
|
||||||
// Access via typed interface
|
// Access via typed interface
|
||||||
});
|
});
|
||||||
|
|
||||||
// ✅ ArkTS - Use for...of for arrays
|
// ✅ ArkTS - Use for...of for arrays
|
||||||
let arr: string[] = ['a', 'b', 'c'];
|
let arr: string[] = ['a', 'b', 'c'];
|
||||||
for (let item of arr) {
|
for (let item of arr) {
|
||||||
console.log(item);
|
console.log(item);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `delete`
|
#### `delete`
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
delete obj.property;
|
delete obj.property;
|
||||||
|
|
||||||
// ✅ ArkTS - Use optional properties
|
// ✅ ArkTS - Use optional properties
|
||||||
interface Config {
|
interface Config {
|
||||||
name: string;
|
name: string;
|
||||||
value?: number; // Optional, can be undefined
|
value?: number; // Optional, can be undefined
|
||||||
}
|
}
|
||||||
let config: Config = { name: 'test', value: undefined };
|
let config: Config = { name: 'test', value: undefined };
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `with`
|
#### `with`
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
with (obj) {
|
with (obj) {
|
||||||
console.log(property);
|
console.log(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS - Use explicit references
|
// ✅ ArkTS - Use explicit references
|
||||||
console.log(obj.property);
|
console.log(obj.property);
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `in` operator for type checking
|
#### `in` operator for type checking
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
if ('name' in person) {
|
if ('name' in person) {
|
||||||
console.log(person.name);
|
console.log(person.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS - Use instanceof
|
// ✅ ArkTS - Use instanceof
|
||||||
if (person instanceof Person) {
|
if (person instanceof Person) {
|
||||||
console.log(person.name);
|
console.log(person.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS - Use discriminated unions
|
// ✅ ArkTS - Use discriminated unions
|
||||||
interface Person { type: 'person'; name: string; }
|
interface Person { type: 'person'; name: string; }
|
||||||
interface Animal { type: 'animal'; species: string; }
|
interface Animal { type: 'animal'; species: string; }
|
||||||
type Entity = Person | Animal;
|
type Entity = Person | Animal;
|
||||||
|
|
||||||
function getName(e: Entity): string {
|
function getName(e: Entity): string {
|
||||||
if (e.type === 'person') {
|
if (e.type === 'person') {
|
||||||
return e.name;
|
return e.name;
|
||||||
}
|
}
|
||||||
return e.species;
|
return e.species;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 7. Interface Constraints
|
### 7. Interface Constraints
|
||||||
|
|
||||||
#### Prohibited: Call signatures and construct signatures
|
#### Prohibited: Call signatures and construct signatures
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
interface Callable {
|
interface Callable {
|
||||||
(x: number): number;
|
(x: number): number;
|
||||||
new (s: string): Object;
|
new (s: string): Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS - Use classes
|
// ✅ ArkTS - Use classes
|
||||||
class Calculator {
|
class Calculator {
|
||||||
calculate(x: number): number {
|
calculate(x: number): number {
|
||||||
return x * 2;
|
return x * 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Factory {
|
class Factory {
|
||||||
create(s: string): Object {
|
create(s: string): Object {
|
||||||
return { value: s };
|
return { value: s };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. Other Restrictions
|
### 8. Other Restrictions
|
||||||
|
|
||||||
| Feature | Status | Alternative |
|
| Feature | Status | Alternative |
|
||||||
|---------|--------|-------------|
|
|---------|--------|-------------|
|
||||||
| Comma expressions | Prohibited (except in `for`) | Separate statements |
|
| Comma expressions | Prohibited (except in `for`) | Separate statements |
|
||||||
| Computed property names | Limited | String literal keys |
|
| Computed property names | Limited | String literal keys |
|
||||||
| Spread on non-arrays | Limited | Explicit copying |
|
| Spread on non-arrays | Limited | Explicit copying |
|
||||||
| `eval()` | Prohibited | Avoid |
|
| `eval()` | Prohibited | Avoid |
|
||||||
| `Function()` constructor | Prohibited | Arrow functions |
|
| `Function()` constructor | Prohibited | Arrow functions |
|
||||||
| Prototype modification | Prohibited | Class inheritance |
|
| Prototype modification | Prohibited | Class inheritance |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Migration Examples
|
## Migration Examples
|
||||||
|
|
||||||
### Example 1: Dynamic Configuration Object
|
### Example 1: Dynamic Configuration Object
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
let config: any = {};
|
let config: any = {};
|
||||||
config.apiUrl = 'https://api.example.com';
|
config.apiUrl = 'https://api.example.com';
|
||||||
config.timeout = 5000;
|
config.timeout = 5000;
|
||||||
config.retry = true;
|
config.retry = true;
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
interface AppConfig {
|
interface AppConfig {
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
timeout: number;
|
timeout: number;
|
||||||
retry: boolean;
|
retry: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let config: AppConfig = {
|
let config: AppConfig = {
|
||||||
apiUrl: 'https://api.example.com',
|
apiUrl: 'https://api.example.com',
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
retry: true
|
retry: true
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example 2: Object Iteration
|
### Example 2: Object Iteration
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
interface User { name: string; age: number; }
|
interface User { name: string; age: number; }
|
||||||
let user: User = { name: 'John', age: 30 };
|
let user: User = { name: 'John', age: 30 };
|
||||||
|
|
||||||
for (let key in user) {
|
for (let key in user) {
|
||||||
console.log(`${key}: ${user[key]}`);
|
console.log(`${key}: ${user[key]}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
interface User {
|
interface User {
|
||||||
name: string;
|
name: string;
|
||||||
age: number;
|
age: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
let user: User = { name: 'John', age: 30 };
|
let user: User = { name: 'John', age: 30 };
|
||||||
console.log(`name: ${user.name}`);
|
console.log(`name: ${user.name}`);
|
||||||
console.log(`age: ${user.age}`);
|
console.log(`age: ${user.age}`);
|
||||||
|
|
||||||
// Or use explicit property list
|
// Or use explicit property list
|
||||||
const props: (keyof User)[] = ['name', 'age'];
|
const props: (keyof User)[] = ['name', 'age'];
|
||||||
for (let prop of props) {
|
for (let prop of props) {
|
||||||
// Handle each known property
|
// Handle each known property
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example 3: Optional Property Handling
|
### Example 3: Optional Property Handling
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
let obj: any = { a: 1 };
|
let obj: any = { a: 1 };
|
||||||
if (obj.b) {
|
if (obj.b) {
|
||||||
delete obj.b;
|
delete obj.b;
|
||||||
}
|
}
|
||||||
obj.c = 3;
|
obj.c = 3;
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
interface MyObj {
|
interface MyObj {
|
||||||
a: number;
|
a: number;
|
||||||
b?: number;
|
b?: number;
|
||||||
c?: number;
|
c?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
let obj: MyObj = { a: 1 };
|
let obj: MyObj = { a: 1 };
|
||||||
if (obj.b !== undefined) {
|
if (obj.b !== undefined) {
|
||||||
obj.b = undefined; // Set to undefined instead of delete
|
obj.b = undefined; // Set to undefined instead of delete
|
||||||
}
|
}
|
||||||
obj.c = 3;
|
obj.c = 3;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example 4: Type Guards
|
### Example 4: Type Guards
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// ❌ TypeScript
|
// ❌ TypeScript
|
||||||
function process(input: unknown) {
|
function process(input: unknown) {
|
||||||
if (typeof input === 'string') {
|
if (typeof input === 'string') {
|
||||||
return input.toUpperCase();
|
return input.toUpperCase();
|
||||||
}
|
}
|
||||||
if ('length' in input) {
|
if ('length' in input) {
|
||||||
return (input as any[]).length;
|
return (input as any[]).length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ ArkTS
|
// ✅ ArkTS
|
||||||
function processString(input: string): string {
|
function processString(input: string): string {
|
||||||
return input.toUpperCase();
|
return input.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function processArray(input: string[]): number {
|
function processArray(input: string[]): number {
|
||||||
return input.length;
|
return input.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use union types with type narrowing
|
// Use union types with type narrowing
|
||||||
type Input = string | string[];
|
type Input = string | string[];
|
||||||
|
|
||||||
function process(input: Input): string | number {
|
function process(input: Input): string | number {
|
||||||
if (typeof input === 'string') {
|
if (typeof input === 'string') {
|
||||||
return input.toUpperCase();
|
return input.toUpperCase();
|
||||||
}
|
}
|
||||||
return input.length;
|
return input.length;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Migration Checklist
|
## Migration Checklist
|
||||||
|
|
||||||
### Phase 1: Enable Strict Mode
|
### Phase 1: Enable Strict Mode
|
||||||
- [ ] Enable `strict: true` in tsconfig.json
|
- [ ] Enable `strict: true` in tsconfig.json
|
||||||
- [ ] Enable `noImplicitAny: true`
|
- [ ] Enable `noImplicitAny: true`
|
||||||
- [ ] Enable `strictNullChecks: true`
|
- [ ] Enable `strictNullChecks: true`
|
||||||
- [ ] Fix all resulting errors
|
- [ ] Fix all resulting errors
|
||||||
|
|
||||||
### Phase 2: Remove Prohibited Keywords
|
### Phase 2: Remove Prohibited Keywords
|
||||||
- [ ] Replace all `var` with `let`/`const`
|
- [ ] Replace all `var` with `let`/`const`
|
||||||
- [ ] Remove all `any` type annotations
|
- [ ] Remove all `any` type annotations
|
||||||
- [ ] Remove all `unknown` type annotations
|
- [ ] Remove all `unknown` type annotations
|
||||||
- [ ] Replace `#` private fields with `private`
|
- [ ] Replace `#` private fields with `private`
|
||||||
|
|
||||||
### Phase 3: Fix Object Patterns
|
### Phase 3: Fix Object Patterns
|
||||||
- [ ] Replace dynamic property access with typed interfaces
|
- [ ] Replace dynamic property access with typed interfaces
|
||||||
- [ ] Remove `delete` statements
|
- [ ] Remove `delete` statements
|
||||||
- [ ] Remove `for...in` loops
|
- [ ] Remove `for...in` loops
|
||||||
- [ ] Remove `with` statements
|
- [ ] Remove `with` statements
|
||||||
- [ ] Replace `in` operator type checks
|
- [ ] Replace `in` operator type checks
|
||||||
|
|
||||||
### Phase 4: Update Interfaces
|
### Phase 4: Update Interfaces
|
||||||
- [ ] Remove call signatures from interfaces
|
- [ ] Remove call signatures from interfaces
|
||||||
- [ ] Remove construct signatures from interfaces
|
- [ ] Remove construct signatures from interfaces
|
||||||
- [ ] Replace structural typing with explicit implements
|
- [ ] Replace structural typing with explicit implements
|
||||||
|
|
||||||
### Phase 5: Validate
|
### Phase 5: Validate
|
||||||
- [ ] Build with ArkTS compiler
|
- [ ] Build with ArkTS compiler
|
||||||
- [ ] Fix remaining errors
|
- [ ] Fix remaining errors
|
||||||
- [ ] Test all functionality
|
- [ ] Test all functionality
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- [Official Migration Guide](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/typescript-to-arkts-migration-guide)
|
- [Official Migration Guide](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/typescript-to-arkts-migration-guide)
|
||||||
- [ArkTS Language Reference](https://developer.huawei.com/consumer/cn/arkts/)
|
- [ArkTS Language Reference](https://developer.huawei.com/consumer/cn/arkts/)
|
||||||
Reference in New Issue
Block a user