我被困在一个简单的例子中,尝试了不同的技巧来缩小类型,但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语句