如何将类型缩小到对象并排除布尔类型



我被困在一个简单的例子中,尝试了不同的技巧来缩小类型,但TS给了我错误。考虑以下示例:

interface IObject {
someField: string
}
interface ISomething {
inner:  IObject | boolean
}
function returnValue(s: string, smth: ISomething): string {
if (s === 'inner')
return smth[s].someField
else 
return ''
}

游乐场链接

如何告诉TS smth['inner']的类型为IObject,不包括布尔类型,这样TS就不会出错:属性'someField'不存在于'boolean | IObject'类型上。类型"false"上不存在属性"someField"。(2339(

只需添加一个额外的条件语句:

interface IObject {
someField: string
}
interface ISomething {
inner: IObject | boolean
}
function returnValue(s: string, smth: ISomething) {
if (s === 'inner') {
const value = smth[s];
// Or typeof value === 'object'
if (typeof value !== 'boolean') {
return value.someField
}
}
return ''
}

游乐场

我认为这是一个使用函数重载的好地方。在这个例子中:

interface IObject<SomeField> {
someField: SomeField
}
interface ISomething<T> {
inner: IObject<T> | boolean
}
function returnValue(s: 'inner', smth: { inner: boolean }): ''
function returnValue<SomeField extends string>(s: 'inner', smth: ISomething<SomeField>): SomeField
function returnValue(s: string, smth: ISomething<string>): ''
function returnValue(s: string, smth: ISomething<string>) {
if (s === 'inner') {
const value = smth[s];
if (typeof value !== 'boolean') {
return value.someField
}
}
return ''
}
const result1 = returnValue('inner', { inner: { someField: 'hello' } }) // "hello"
const result2 = returnValue('inner', { inner: true }) // ""
const result3 = returnValue('other', { inner: true }) // ""

游乐场

(<ISomething>smth['inner']).someField

这应该工作

您可以检查if(smth['inner'] instanceof boolean)的类型

然后你可以用写if语句

最新更新