20260227-1

This commit is contained in:
cyh666666
2026-02-27 16:51:56 +08:00
1526 changed files with 2457 additions and 38509 deletions

View File

@@ -1394,3 +1394,598 @@ getCurrentUserId 函数 - 将可选链替换为显式 null 检查和 UTSJSONObje
================================================================================
文档结束
================================================================================
================================================================================
二十四、2026-02-27 函数可选参数限制(重要)
================================================================================
1. 可选参数不能跳过传递
- UTS Android 不支持跳过可选参数传递
- 如果函数有多个可选参数,必须按顺序传递所有参数
- 错误示例:
```typescript
// 函数定义
async addToCart(productId: string, quantity: number = 1, skuId?: string, merchantId?: string): Promise<boolean>
// 错误调用 - 跳过了 merchantId 参数
await supabaseService.addToCart(productId, 1, '')
// 编译错误No value passed for parameter 'merchantId'
```
- 正确示例:
```typescript
// 方案1给可选参数添加默认值
async addToCart(productId: string, quantity: number = 1, skuId: string = '', merchantId: string = ''): Promise<boolean>
// 方案2调用时传递所有参数
await supabaseService.addToCart(productId, 1, '', '')
```
2. 可选参数定义规范
- 推荐使用 `param: Type = defaultValue` 而非 `param?: Type`
- `param?: Type` 在 Android 端调用时仍需传递参数
- `param: Type = defaultValue` 可以在不传参时使用默认值
- 示例:
```typescript
// 不推荐 - 调用时仍需传递参数
function foo(a: string, b?: string, c?: string): void
// 推荐 - 可以跳过参数使用默认值
function foo(a: string, b: string = '', c: string = ''): void
```
3. 编译错误提示
- 错误信息:"No value passed for parameter 'xxx'"
- 原因:可选参数在 Android 端不能跳过
- 解决:
1. 修改函数签名,使用默认值 `param: Type = defaultValue`
2. 调用时传递所有参数
4. 最佳实践
- 对于有多个可选参数的函数,统一使用默认值语法
- 调用时显式传递所有参数,避免依赖可选参数跳过
- 在服务层函数定义中,优先使用 `= ''` 或 `= 0` 等默认值
================================================================================
二十五、2026-02-27 模板中的非空断言限制(重要)
================================================================================
1. 模板中不支持非空断言操作符 `!`
- UTS Android 模板中不能使用 `variable!` 非空断言
- 错误示例:
```html
<text v-if="product.original_price != null && product.original_price! > product.price">
```
- 正确示例:
```html
<text v-if="product.original_price != null && product.original_price > product.price">
```
2. 编译错误提示
- 错误信息:"参数类型不匹配:实际类型为 'Number?',预期类型为 'Number'"
- 原因:模板中使用非空断言 `!` 不被支持
- 解决:移除非空断言 `!`,直接使用变量进行比较
3. 最佳实践
- 在模板中,先用 `!= null` 判断可空类型,然后直接使用变量
- UTS 编译器会在 `!= null` 判断后自动识别变量为非空类型
================================================================================
二十六、2026-02-27 未导入类型的处理(重要)
================================================================================
1. 未导入的类型不能直接使用
- 在页面中使用的类型必须先导入或使用 UTSJSONObject 替代
- 错误示例:
```typescript
// Shop 类型未导入
const s = shopRespData[i] as Shop
const id = s.id // 找不到名称 "id"
```
- 正确示例:
```typescript
// 使用 UTSJSONObject
const s = shopRespData[i] as UTSJSONObject
const id = s.getString('id') ?? ''
const name = s.getString('shop_name') ?? ''
```
2. 编译错误提示
- 错误信息:"找不到名称 'XXX'"
- 原因:类型未导入或类型定义不存在
- 解决:
1. 导入需要的类型:`import { Shop } from '@/utils/supabaseService.uts'`
2. 使用 UTSJSONObject 替代:`as UTSJSONObject` 然后用 `getString()`、`getNumber()` 访问属性
3. 最佳实践
- 对于简单的数据转换,推荐使用 UTSJSONObject
- 避免在多个文件中重复定义相同的类型
- 如果需要类型安全,从服务层导入类型定义
================================================================================
二十七、2026-02-27 服务层数据字段完整性(重要)
================================================================================
1. 服务层返回数据必须包含所有必要字段
- 从数据库获取数据时,必须正确映射所有需要的字段
- 错误示例:
```typescript
const product: Product = {
id: prodObj.getString('id') ?? '',
name: prodObj.getString('name') ?? '',
// 错误merchant_id 硬编码为空字符串
merchant_id: ''
} as Product
```
- 正确示例:
```typescript
const product: Product = {
id: prodObj.getString('id') ?? '',
name: prodObj.getString('name') ?? '',
// 正确:从数据库获取 merchant_id
merchant_id: prodObj.getString('merchant_id') ?? ''
} as Product
```
2. 调用服务层方法时必须传递完整参数
- 页面调用服务层方法时,需要传递所有必要参数
- 错误示例:
```typescript
// 错误merchant_id 传空字符串
await supabaseService.addToCart(productId, 1, '', '')
```
- 正确示例:
```typescript
// 正确:从商品对象获取 merchant_id
const merchantId = product.merchant_id ?? ''
await supabaseService.addToCart(productId, 1, '', merchantId)
```
3. 编译错误提示
- 问题表现:数据添加到数据库失败,或添加的数据不完整
- 原因:服务层或页面层缺少必要字段的传递
- 解决:
1. 检查服务层数据映射是否完整
2. 检查页面调用时是否传递了所有必要参数
4. 最佳实践
- 服务层方法返回的对象应包含数据库视图的所有字段
- 页面调用服务层方法时,应从数据对象中获取并传递所有参数
- 对于关联数据(如 merchant_id确保在数据加载时一并获取
================================================================================
二十八、2026-02-27 模板中的非运算符限制(重要)
================================================================================
1. 模板中不支持 `!` 非运算符
- UTS Android 模板中不能使用 `!variable` 非运算符
- 错误示例:
```html
<view v-if="!brand.logo_url">
```
- 正确示例:
```html
<view v-if="brand.logo_url == null || brand.logo_url == ''">
```
2. 编译错误提示
- 错误信息:"找不到名称'not'"
- 原因:模板中不支持非运算符 `!`
- 解决:使用显式的比较表达式替代
3. 最佳实践
- 使用 `== null` 或 `== ''` 检查空值
- 使用 `!= null && != ''` 检查非空值
================================================================================
二十九、2026-02-27 索引访问限制(重要)
================================================================================
1. 不支持 `(obj as any)['key']` 索引访问方式
- UTS Android 不支持对 any 类型使用索引访问
- 错误示例:
```typescript
const detail = (e as any)['detail']
val = detail['value'] ?? ''
```
- 正确示例:
```typescript
// 方案1使用 UTSJSONObject
const eObj = JSON.parse(JSON.stringify(e)) as UTSJSONObject
const detail = eObj.get('detail') as UTSJSONObject
val = detail.getString('value') ?? ''
// 方案2先判断类型再转换
if (e instanceof UTSJSONObject) {
const eObj = e as UTSJSONObject
const detail = eObj.get('detail') as UTSJSONObject
val = detail.getString('value') ?? ''
}
```
2. 编译错误提示
- 错误信息:"Unresolved reference. None of the following candidates is applicable because of a receiver type mismatch"
- 原因any 类型不支持索引访问
- 解决:转换为 UTSJSONObject 后使用 `.get()` 方法
3. 最佳实践
- 统一使用 UTSJSONObject 处理动态对象
- 使用 `.get()`、`.getString()`、`.getNumber()` 方法访问属性
- 对于复杂对象,先用 `JSON.parse(JSON.stringify(obj))` 转换
================================================================================
三十、2026-02-27 字符串不能直接作为布尔条件(重要)
================================================================================
1. 字符串不能直接作为 if 条件
- UTS Android 不支持将字符串直接作为布尔条件判断
- 错误示例:
```typescript
const paramId = '123'
if (paramId) { // 错误:字符串不能直接作为布尔条件
// ...
}
```
- 正确示例:
```typescript
const paramId = '123'
if (paramId != null && paramId != '') { // 正确:显式判断
// ...
}
```
2. 编译错误提示
- 错误信息:"Condition type mismatch: inferred type is 'String' but 'Boolean' was expected"
- 原因:字符串类型不能直接作为布尔条件
- 解决:使用显式的比较表达式
3. 最佳实践
- 使用 `!= null && != ''` 检查字符串非空
- 使用 `== null || == ''` 检查字符串为空
================================================================================
三十一、2026-02-27 函数定义顺序(重要)
================================================================================
1. 函数必须在调用前定义
- UTS Android 要求函数在调用之前完成定义
- 这与 JavaScript 的函数提升不同
- 错误示例:
```typescript
onMounted(() => {
loadData() // 错误loadData 还未定义
})
const loadData = async () => {
// ...
}
```
- 正确示例:
```typescript
const loadData = async () => {
// ...
}
onMounted(() => {
loadData() // 正确loadData 已定义
})
```
2. 编译错误提示
- 错误信息:"找不到名称'xxx'"
- 原因:函数在调用点之后定义
- 解决:将函数定义移到调用之前
3. 最佳实践
- 将所有函数定义放在生命周期钩子onMounted、onShow 等)之前
- 按依赖关系排序函数定义顺序
================================================================================
三十二、2026-02-27 联合类型属性访问(重要)
================================================================================
1. 联合类型不能直接访问属性
- 当参数类型为联合类型(如 `A | B`)时,不能直接访问属性
- 错误示例:
```typescript
type A = { id: string, name: string }
type B = { id: string, title: string }
const foo = (item: A | B) => {
const id = item.id // 错误:联合类型不能直接访问属性
}
```
- 正确示例:
```typescript
const foo = (item: A | B) => {
// 方案1转换为 UTSJSONObject
const obj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
const id = obj.getString('id') ?? ''
// 方案2使用类型守卫
if ('name' in item) {
const id = item.id // 此时类型已收窄为 A
}
}
```
2. 编译错误提示
- 错误信息:"找不到名称'xxx'"
- 原因:联合类型的属性访问受限
- 解决:转换为 UTSJSONObject 或使用类型守卫
3. 最佳实践
- 对于联合类型参数,统一转换为 UTSJSONObject 处理
- 使用 `.getString()`、`.getNumber()` 等方法安全访问属性
================================================================================
三十三、2026-02-27 any 类型变量不能赋值为 null重要
================================================================================
1. any 类型变量不能赋值为 null
- UTS Android 中 `any` 类型不能赋值为 `null`
- 错误示例:
```typescript
let res: any = null // 错误Null cannot be a value of a non-null type 'Any'
```
- 正确示例:
```typescript
let res: any = {} // 正确:使用空对象
// 或者
let res: any | null = null // 使用联合类型
```
2. 编译错误提示
- 错误信息:"Null cannot be a value of a non-null type 'Any'"
- 原因any 类型不允许 null 值
- 解决:使用空对象 `{}` 或联合类型 `any | null`
================================================================================
三十四、2026-02-27 对象字面量类型推断问题(重要)
================================================================================
1. 对象字面量直接赋值给 ref 可能类型不匹配
- 当对象字面量直接赋值给特定类型的 ref 时,可能报类型不匹配错误
- 错误示例:
```typescript
merchant.value = {
id: shop.id,
user_id: shop.merchant_id,
// ...
} // 错误Assignment type mismatch
```
- 正确示例:
```typescript
// 方案1显式声明类型
const merchantData: MerchantType = {
id: shop.id,
user_id: shop.merchant_id,
// ...
}
merchant.value = merchantData
// 方案2使用 as 类型断言
merchant.value = {
id: shop.id,
user_id: shop.merchant_id,
// ...
} as MerchantType
```
2. 编译错误提示
- 错误信息:"Assignment type mismatch: actual type is '<anonymous>', but 'XXX' was expected"
- 原因:对象字面量被推断为匿名类型
- 解决:显式声明类型或使用类型断言
================================================================================
三十五、2026-02-27 any 类型不能直接访问属性(重要)
================================================================================
1. any 类型参数不能直接访问属性
- 在 map、forEach 等回调中any 类型的参数不能直接访问属性
- 错误示例:
```typescript
const list = rawList.map((item): ProductType => {
const id = item.id // 错误:找不到名称"id"
const name = item.name // 错误:找不到名称"name"
})
```
- 正确示例:
```typescript
const list = rawList.map((item: any): ProductType => {
// 方案1转换为 UTSJSONObject
const itemObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
const id = itemObj.getString('id') ?? ''
const name = itemObj.getString('name') ?? ''
// 方案2显式标注参数类型并使用索引
// 注意:这种方式在 UTS Android 中也可能有问题
})
```
2. 编译错误提示
- 错误信息:"找不到名称'xxx'"
- 原因any 类型的属性访问受限
- 解决:转换为 UTSJSONObject 后使用 `.getString()` 等方法
================================================================================
三十六、2026-02-27 类型断言不会添加方法(重要)
================================================================================
1. `as UTSJSONObject` 不会给对象添加方法
- 使用 `as UTSJSONObject` 只是类型断言,不会让普通对象获得 `getString` 等方法
- 错误示例:
```typescript
const profileObj = profile as UTSJSONObject
const id = profileObj.getString('user_id') // 运行时错误getString is not a function
```
- 正确示例:
```typescript
// 必须使用 JSON.parse(JSON.stringify()) 进行真正的转换
const profileObj = JSON.parse(JSON.stringify(profile)) as UTSJSONObject
const id = profileObj.getString('user_id') ?? ''
```
2. 运行时错误提示
- 错误信息:"XXX is not a function"
- 原因:类型断言只是编译时行为,不会改变运行时对象的方法
- 解决:使用 `JSON.parse(JSON.stringify())` 进行真正的对象转换
3. 最佳实践
- 对于从 API 返回的数据,统一使用 `JSON.parse(JSON.stringify())` 转换
- 使用 `instanceof UTSJSONObject` 检查对象类型
- 不要依赖 `as` 类型断言来添加方法
================================================================================
三十七、2026-02-27 类型必须包含所有必填字段(重要)
================================================================================
1. 创建类型实例时必须包含所有必填字段
- UTS 类型定义中的非可选字段(不带 `?`)都是必填的
- 错误示例:
```typescript
export type ProductType = {
id: string
merchant_id: string // 必填
category_id: string // 必填
name: string
// ...
}
// 错误:缺少 merchant_id、category_id 等必填字段
return {
id: item.id,
name: item.name,
price: item.price
} as ProductType // 运行时错误missing required property
```
- 正确示例:
```typescript
return {
id: itemObj.getString('id') ?? '',
merchant_id: itemObj.getString('merchant_id') ?? '',
category_id: itemObj.getString('category_id') ?? '',
name: itemObj.getString('name') ?? '未知商品',
description: itemObj.getString('description') ?? '',
images: images,
price: itemObj.getNumber('base_price') ?? 0,
original_price: itemObj.getNumber('market_price') ?? 0,
stock: itemObj.getNumber('total_stock') ?? 0,
sales: itemObj.getNumber('sale_count') ?? 0,
status: 1,
created_at: itemObj.getString('created_at') ?? ''
} as ProductType
```
2. 运行时错误提示
- 错误信息:"Failed to construct type, missing required property: xxx"
- 原因:类型定义中有必填字段未提供
- 解决:
1. 检查类型定义,确认所有必填字段
2. 为所有必填字段提供值,即使是空字符串或默认值
3. 最佳实践
- 查看类型定义,确认哪些字段是必填的(不带 `?`
- 使用 `??` 运算符提供默认值
- 对于可选字段,可以不提供或使用 `null`
================================================================================
三十八、2026-02-27 回调函数不能是 async重要
================================================================================
1. API 回调函数不能使用 async 修饰
- uni API 的回调函数(如 showModal 的 success不支持 async 函数
- 错误示例:
```typescript
uni.showModal({
title: '确认',
content: '确定要删除吗?',
success: async (res) => { // 错误:回调函数不能是 async
if (res.confirm) {
const result = await someAsyncFunction()
}
}
})
```
- 正确示例:
```typescript
uni.showModal({
title: '确认',
content: '确定要删除吗?',
success: (res) => {
if (res.confirm) {
// 使用 Promise.then() 代替 await
someAsyncFunction().then((result) => {
// 处理结果
})
}
}
})
```
2. 编译错误提示
- 错误信息:"参数类型不匹配:实际类型为 'Function1<..., UTSPromise<Unit>>',预期类型为 'Function1<..., Unit>?'"
- 原因:回调函数返回 Promise 而非 void
- 解决:使用 `.then()` 代替 `await`
3. 最佳实践
- 在回调函数中使用 `.then()` 处理异步操作
- 将异步逻辑封装为单独的函数,在回调中调用
================================================================================
三十九、2026-02-27 类型转换前必须检查类型(重要)
================================================================================
1. 使用 `as` 类型转换前必须检查实际类型
- 直接使用 `as string` 转换可能导致运行时类型转换异常
- 错误示例:
```typescript
const idVal = item['id']
const id = idVal as string // 错误:如果 idVal 是其他类型会崩溃
```
- 正确示例:
```typescript
const idVal = item['id']
const id = (idVal != null && typeof idVal == 'string') ? (idVal as string) : ''
```
2. 运行时错误提示
- 错误信息:"null cannot be cast to non-null type kotlin.String"
- 错误信息:"java.lang.Boolean cannot be cast to java.lang.String"
- 原因:直接类型转换时,实际类型与目标类型不匹配
- 解决:使用 `typeof` 检查类型后再转换
3. 最佳实践
- 使用 `typeof` 检查类型
- 使用 `!= null` 检查空值
- 提供默认值防止空指针异常
================================================================================
四十、2026-02-27 UTSJSONObject 必须正确转换(重要)
================================================================================
1. `as UTSJSONObject` 不会添加方法
- 从数据库返回的数据需要正确转换为 UTSJSONObject
- 错误示例:
```typescript
const item = rawList[i]
const brandObj = item as UTSJSONObject // 错误brandObj.getString 不存在
```
- 正确示例:
```typescript
const item = rawList[i]
const brandObj = JSON.parse(JSON.stringify(item)) as UTSJSONObject
const id = brandObj.getString('id') ?? ''
```
2. 运行时错误提示
- 错误信息:"getString is not a function"
- 原因:对象没有正确转换为 UTSJSONObject
- 解决:使用 `JSON.parse(JSON.stringify())` 进行转换
3. 最佳实践
- 对于从数据库/API 返回的数据,统一使用 `JSON.parse(JSON.stringify())` 转换
- 使用 `.getString()`、`.getNumber()` 等方法安全访问属性
================================================================================
================================================================================