写惯了 js 再写 ts 时会出现很多类型报错比如用后端传来 json 数据进行遍历取值时,对于某个遍历的item执行某些属性或方法,会出现一下报错:
unknown和any都属于 TypeScript 的顶层类型,且官方更推荐的变量的类型是 unknown 而不是 any。官网解释如下:
unknown is safer than any because it reminds us that we need to perform some sort of type-checks before operating on our values.
因为,变量类型一旦设为any
,TypeScript 实际上会关闭这个变量的类型检查,问题就这样留到运行时才会暴露。。即使有明显的类型错误,只要句法正确,都不会报错。这样会“污染”其他变量。它可以赋值给其他任何类型的变量(因为没有类型检查),导致其他变量出错。如:
let x:any = 'hello';
let y:number;
y = x; // 不报错
y * 123 // 不报错
y.toFixed() // 不报错
为了解决any
类型“污染”其他变量的问题,TypeScript 3.0 引入了unknown类型。它与any
含义相同,表示类型不确定,可能是任意类型,但是它的使用有一些限制,不像any
那样自由,可以视为严格版的any
。
unknown
跟any
的相似之处,在于所有类型的值都可以分配给unknown
类型。
unknown
类型跟any
类型的不同之处在于,它不能直接使用。主要有以下几个限制:
1. unknown
类型的变量,不能直接赋值给其他类型的变量(除了any
类型和unknown
类型)。
let v:unknown = 123;
let v1:boolean = v; // 报错
let v2:number = v; // 报错
2. 能直接调用unknown
类型变量的方法和属性。
let v1:unknown = { foo: 123 };
v1.foo // 报错
let v2:unknown = 'hello';
v2.trim() // 报错
let v3:unknown = (n = 0) => n + 1;
v3() // 报错
3. unknown
类型变量能够进行的运算是有限的,只能进行比较运算(运算符==
、===
、!=
、!==
、||
、&&
、?
)、取反运算(运算符!
)、typeof
运算符和instanceof
运算符这几种,其他运算都会报错。
let a:unknown = 1;
a + 1 // 报错
a === 1 // 正确
要使用unknown
类型变量,须经过“类型缩小”:
let a:unknown = 1;
if (typeof a === 'number') {
let r = a + 10; // 正确
}
上面示例中,unknown
类型的变量a
经过typeof
运算以后,能够确定实际类型是number
,就能用于加法运算了。这就是“类型缩小”,即将一个不确定的类型缩小为更明确的类型。
言归正传,解决办法就是在使用变量之前做类型声明
比如,你从后端请求的数据 格式 如下:
let data =
[
{
"datas": [
{
"id": 0,
"operator": "Delete package"
},
{
"id": 1,
"operator": "Edit label"
}
],
"module": "Package Info"
},
{
"datas": [
{
"id": 2,
"operator": "Operator package"
},
{
"id": 3,
"operator": "Add new category"
},
],
"module": "Vehicle(Bench) Info"
},
]
需要自定义数组接口:
interface IList {
'module': string;
'datas': [
{
'id': number,
'operator': string
}
];
}
interface ILists extends Array<IList>{}
并且在声明变量 list (用于保存后端传的数据)时注明类型 ILists :
const [list, setList] = useState<ILists>([]);