TypeScript未正确检查对象属性
我有一个对象,它有字符串和数字属性值。当我想设置某些字段类型的值时,当使用TypeScript未正确检查对象属性,typescript,Typescript,我有一个对象,它有字符串和数字属性值。当我想设置某些字段类型的值时,当使用indexOf方法进行检查时,脚本在检查属性类型时失败 下面是一个例子: type TSomeObject = { title: string, description: string, count: number } const someFunction = (myObj: TSomeObject, field: keyof TSomeObject, newValue: string): TSomeObje
indexOf
方法进行检查时,脚本在检查属性类型时失败
下面是一个例子:
type TSomeObject = {
title: string,
description: string,
count: number
}
const someFunction = (myObj: TSomeObject, field: keyof TSomeObject, newValue: string): TSomeObject => {
if (field === 'title' || field === 'description') {
myObj[field] = newValue
}
return myObj
}
const otherFunction = (myObj: TSomeObject, field: keyof TSomeObject, newValue: string): TSomeObject =>{
const editableFields = ['title', 'description']
if (editableFields.indexOf(field) >= 0) {
// TypeScript error here
myObj[field] = newValue
}
return myObj
}
请参见中的示例
当someFunction
工作正常时,otherFunction
失败并出现TypeScript错误:
类型“string”不可分配给类型“never”
我知道它与类型为
number
的count
属性相关,但我检查了要编辑的字段。我做错了什么?这里发生了一些事情
一种是,
editableFields
被推断为string[]
,这对于您的目的来说太宽了。自TS3.4以来,您可以使用a来推断更窄的文字类型:
const editableFields = ['title', 'description'] as const;
// const editableFields: readonly ["title", "description"]
现在,editableFields
是一个元组,其成员已知为“title”
和“description”
接下来,TypeScript不会将
arr.indexOf(x)>=0的结果作为x
类型的a。因此,即使测试为true
,x
的类型也不会自动缩小为typeofarr[number]
。这只是TypeScript的一个限制;并非所有可能的测试方法都能被编译器检测到。幸运的是,TypeScript使您能够。在这种情况下,您可能希望制作如下内容:
declare function arrayContains<T extends U, U>(
haystack: ReadonlyArray<T>,
needle: U
): needle is T;
function arrayContains<T extends U, U>(haystack: ReadonlyArray<T>, needle: U): needle is T {
const widenedHaystack: ReadonlyArray<U> = haystack;
return widenedHaystack.indexOf(needle) >= 0;
}
因此,让我们实现arrayContains()
下一件事是:这是:
幸运的是,您可以安全地将ReadonlyArray
扩展为ReadonlyArray
,因此您可以这样编写:
declare function arrayContains<T extends U, U>(
haystack: ReadonlyArray<T>,
needle: U
): needle is T;
function arrayContains<T extends U, U>(haystack: ReadonlyArray<T>, needle: U): needle is T {
const widenedHaystack: ReadonlyArray<U> = haystack;
return widenedHaystack.indexOf(needle) >= 0;
}
函数数组内容(haystack:ReadonlyArray,指针:U):指针是T{
康斯特加宽干草堆:ReadonlyArray=干草堆;
返回加宽草垛。索引(针)>=0;
}
这就行了!相反,您也可以只使用a使编译器静音,如中所示:
function arrayContains<T extends U, U>(haystack: ReadonlyArray<T>, needle: U): needle is T {
return haystack.indexOf(needle as T) >= 0; // assert
}
函数数组内容(haystack:ReadonlyArray,指针:U):指针是T{
返回haystack.indexOf(针作为T)>=0;//断言
}
但我通常会尽量避免断言,除非它们是必要的,而在这里它们不是。这取决于你
所以,让我们把这一切放在一起:
function arrayContains<T extends U, U>(haystack: ReadonlyArray<T>, needle: U): needle is T {
const widenedHaystack: ReadonlyArray<U> = haystack;
return widenedHaystack.indexOf(needle) >= 0;
}
function otherFunction(myObj: TSomeObject, field: keyof TSomeObject, newValue: string): TSomeObject {
const editableFields = ['title', 'description'] as const;
if (arrayContains(editableFields, field)) {
myObj[field] = newValue
}
return myObj
}
函数数组内容(haystack:ReadonlyArray,指针:U):指针是T{
康斯特加宽干草堆:ReadonlyArray=干草堆;
返回加宽草垛。索引(针)>=0;
}
函数otherFunction(myObj:TSomeObject,字段:keyof TSomeObject,newValue:string):TSomeObject{
常量editableFields=['title','description']作为常量;
if(数组内容(可编辑字段,字段)){
myObj[field]=新值
}
返回myObj
}
好的,希望能有帮助。祝你好运
可编辑字段的类型为字符串[]。我试图设置正确的类型,例如:const editableFields:Array=['title','description'],但这只会导致indexOf不起作用work@jcalz操场链接现在已修复。回答得很好!谢谢
function arrayContains<T extends U, U>(haystack: ReadonlyArray<T>, needle: U): needle is T {
const widenedHaystack: ReadonlyArray<U> = haystack;
return widenedHaystack.indexOf(needle) >= 0;
}
function otherFunction(myObj: TSomeObject, field: keyof TSomeObject, newValue: string): TSomeObject {
const editableFields = ['title', 'description'] as const;
if (arrayContains(editableFields, field)) {
myObj[field] = newValue
}
return myObj
}