如何解决 TypeScript 中 Type ‘unknown’ is not assignable to type 错误
当我们尝试将类型为未知的值分配给不同类型的值时,会发生“Type ‘unknown’ is not assignable to type”错误。 要解决该错误,请在赋值之前使用类型断言或类型保护来验证两个值是否具有兼容的类型。
下面是产生上述错误的示例。
const a: unknown = 'James';
// ⛔️ Error: Type 'unknown' is
// not assignable to type 'string'.ts(2322)
const b: string = a;
a
变量的类型未知。
这通常发生在从远程 API 获取数据时,因为 TypeScript 不知道我们正在使用的值的类型。
unknown
类型是 any
的类型安全类型。
如果我们确定特定值具有兼容类型,但 TypeScript 不知道,请使用类型断言,例如
value as RightType
。
const a: unknown = 'James';
const b: string = a as string;
当我们有关于 TypeScript 不知道的值类型的信息时,使用类型断言。
我们有效地告诉 TypeScript a 变量将是一个字符串,不用担心。
现在左侧和右侧的值具有兼容的类型,赋值不会导致错误。
另一种解决方案是使用类型保护。
const a: unknown = 'James';
let b = '';
if (typeof a === 'string') {
b = a;
}
console.log(b); // 👉️ "James"
在进行赋值之前,我们明确检查变量 a 是否存储了字符串类型的值。
TypeScript 知道一旦我们进入 if 块,变量 a 就保证是一个字符串。
当处理未知类型时,我们基本上告诉 TypeScript——我们将获得这个值,但我们不知道它的类型。 我们只是要检查几个 if 语句来跟踪它并安全地使用它。 在 if
块中,为我们提供对所检查的特定类型的支持。
下面是一个在处理对象时如何使用类型保护的例子。
const person: unknown = {
name: 'James',
country: 'Chile',
};
type Person = {
name: string;
country: string;
};
// 👇️ checks if obj has properties of Person
function isPerson(obj: any): obj is Person {
return (
typeof obj === 'object' &&
obj !== null &&
'name' in obj &&
'country' in obj
);
}
let james: Person;
if (isPerson(person)) {
// 👉️ person has type of Person here
james = person;
} else {
james = { name: '', country: '' };
}
console.log(james); // 👉️ {name: 'James', country: 'Chile'}
我们使用用户定义的类型保护来检查对象是否具有 Person 类型的所有属性。
obj is Person
语法是一个类型谓词,其中 obj 必须是函数采用的参数的名称。
如果 isPerson
函数返回 true,TypeScript 就知道传入的值是 Person
类型,并允许我们将其分配给变量。
上面的示例只是检查传入的值是否是一个对象并包含名称和国家/地区属性。
我们还必须检查 null,因为在 JavaScript(和 TypeScript)中,typeof null
返回“object”。
如果 person 变量不存储兼容类型的值,我们将使用默认值。
我们还可以在初始化变量时设置默认值。
const person: unknown = {
name: 'James',
country: 'Chile',
};
type Person = {
name: string;
country: string;
};
// 👇️ set defaults upon initialization
let james: Person = {
name: '',
country: '',
};
// 👇️ checks if obj has properties of Person
function isPerson(obj: any): obj is Person {
return (
typeof obj === 'object' &&
obj !== null &&
'name' in obj &&
'country' in obj
);
}
if (isPerson(person)) {
// 👉️ person is type Person here
james = person;
}
// 👇️ {name: 'James', country: 'Chile'}
console.log(james);
是否能够使用此方法取决于用例。
目标是确保分配的左侧和右侧的值具有兼容的类型。
下面是一个示例,说明如何使用类型保护来检查未知类型的值是否为数组。
const data: unknown = [
{
name: 'James',
country: 'Chile',
},
{
name: 'Alice',
country: 'Germany',
},
];
type Person = {
name: string;
country: string;
};
let people: Person[] = [];
if (Array.isArray(data)) {
people = data as Person[];
}
// [
// { name: 'James', country: 'Chile' },
// { name: 'Alice', country: 'Germany' }
// ]
console.log(people);
我们使用 Array.isArray()
方法在赋值之前检查数据变量是否存储了一个数组。
我们可能必须更加严格并检查数组是否有任何元素以及它们是否包含特定属性等。
总结
当我们尝试将类型为未知的值分配给不同类型的值时,会发生“Type ‘unknown’ is not assignable to type”错误。 要解决该错误,请在赋值之前使用类型断言或类型保护来验证两个值是否具有兼容的类型。