I'm trying to tighten up my TS code by using a stricter lint ruleset, but I'm struggling with what should be legitimate uses of dynamism.
I'm making a type guard to detect if something is iterable (to wrap it in an array if not), and I have no idea what to tell TS other than suppressing the lint rule to tell this is kosher:
function isIterable(obj: any): obj is Iterable<unknown> {
return obj && typeof obj[Symbol.iterator] === 'function';
}
I tried changing this to:
function isIterable(obj: undefined | {[Symbol.iterator]?: unknown}): obj is Iterable<unknown> {
return !!obj && typeof obj[Symbol.iterator] === 'function';
}
which compiles without using any
, but it's not useful, because I want to pass values of unknown type to it.
Is there a "clean" way of saying "yes I actually want to rely on JS returning undefined
for accessing a property that doesn't exist on an object"? Esp. since that's kind of whole point of writing type guards.
isIterable(obj: unknown): obj is Iterable<unknown>
? – Muddlerunknown
without a type assertion. It's also not legal to access an arbitrary property onobject
without turning onsuppressImplicitAnyIndexErrors
; and even then you're not allowed to do obj.foo, and a linter will complain about obj['foo']. (It will work for obj[Symbol.whatever], which is a workaround for the above situation, but not for others where I want to narrow the type by a string-named key, i.e. 'then' for promises.) – Rutherford