I am stuck in simple example, tried different tricks to narrow type but TS giving me errors. Consider following example:
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 ''
}
How would you tell TS that smth['inner'] is of type IObject, excluding boolean type so TS won't error: Property 'someField' does not exist on type 'boolean | IObject'. Property 'someField' does not exist on type 'false'.(2339)
CodePudding user response:
Just add an extra condition statement:
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 ''
}
I think this is a good place to use function overloadings. COnsider this example:
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 }) // ""
CodePudding user response:
(<ISomething>smth['inner']).someField
This should work
You can check for type of if(smth['inner'] instanceof boolean)
Then you can write if statements with that