Angular中如何约束InputSignal值至指定数值范围
为Angular组件的InputSignal添加数字数组约束
要实现你需要的输入约束(数字数组,每个元素在0.01-10之间、小数位数不超2位),需要结合编译时类型校验和运行时校验双管齐下,既能在开发阶段提前提示,也能在运行时明确告知非法输入。
1. 定义编译时的合法数字类型
TypeScript无法直接通过基础类型精确限制数字范围和小数位数,但可以通过「品牌类型」+「类型守卫」来实现编译时的约束:
// 带品牌标记的类型,避免普通数字直接赋值 type ValidNumber = number & { __brand: 'ValidNumber' }; // 类型守卫函数,同时用于编译时类型推断和运行时校验 function isValidNumber(num: number): num is ValidNumber { // 校验数值范围 if (num < 0.01 || num > 10) return false; // 校验小数位数不超过2位 const decimalPart = num.toString().split('.')[1]; return !decimalPart || decimalPart.length <= 2; }
2. 配置InputSignal并添加运行时校验
方式一:利用transform选项做即时校验
在input()的配置中使用transform,直接在输入转换时校验并抛出错误,阻止非法值进入组件:
import { input, InputSignal } from '@angular/core'; export class MyComponent { public readonly value: InputSignal<ValidNumber[]> = input<number[]>([], { transform: (rawValues: number[]) => { const invalidEntries = rawValues.filter(num => !isValidNumber(num)); if (invalidEntries.length) { const errorMsg = `[MyComponent] 非法输入:传入的数组包含不符合约束的值:${invalidEntries.join(', ')}。要求:数值在0.01-10之间,小数位数不超过2位。`; console.error(errorMsg); // 抛出错误终止组件初始化,或返回默认合法值(根据需求调整) throw new Error(errorMsg); } // 类型断言:已经通过校验,转换为合法类型 return rawValues as ValidNumber[]; } }); }
方式二:监听信号变化做警告提示
如果不想终止组件运行,只是给开发者警告,可以用effect监听信号变化:
import { input, InputSignal, effect } from '@angular/core'; export class MyComponent { // 先接收普通数字数组,再通过类型断言转为合法类型 public readonly value: InputSignal<ValidNumber[]> = input<number[]>([]) as InputSignal<ValidNumber[]>; constructor() { // 监听信号值变化,实时校验 effect(() => { const currentValues = this.value(); const invalidEntries = currentValues.filter(num => !isValidNumber(num)); if (invalidEntries.length) { console.warn(`[MyComponent] 注意:传入的数组包含不符合约束的值:${invalidEntries.join(', ')}。要求:数值在0.01-10之间,小数位数不超过2位。`); } }); } }
3. 优化校验逻辑(处理浮点数精度问题)
浮点数的精度问题可能导致0.3被存储为0.30000000000000004,可以优化校验函数,通过字符串正则匹配避免这个问题:
function isValidNumber(num: number): num is ValidNumber { if (num < 0.01 || num > 10) return false; // 转换为字符串并去除末尾无效0,避免科学计数法影响 const numStr = num.toFixed(10).replace(/0+$/, '').replace(/\.$/, ''); // 正则匹配:整数或带1-2位小数的数字 return /^\d+(\.\d{1,2})?$/.test(numStr); }
4. 开发者使用示例
其他组件传入值时,合法值可以直接使用,非法值会在编译时(如果严格使用ValidNumber类型)或运行时被提示:
<!-- 合法输入 --> <app-my-component [value]="[0.01, 5, 10, 3.14]"></app-my-component> <!-- 非法输入:会触发错误/警告 --> <app-my-component [value]="[0, 10.01, 2.345]"></app-my-component>
内容的提问来源于stack exchange,提问作者Ryley38
相关产品推荐
相关产品推荐

