TS7017 implict any type + type inference
TS7017 implict any type + type inference
Here's the condensed snippet that's erroring:
export default function formatSql(this: EscapeFunctions, sqlQuery: string, values: QueryParams)
if (isPlainObject(values))
console.log(values[p]); // <-- Element implicitly has an 'any' type because type 'QueryParams' has no index signature.
else if (Array.isArray(values))
// ...
else
throw new Error(`Unsupported values type`);
// ...
QueryParams
is defined as:
QueryParams
export type QueryParams = StringMap | any;
export interface StringMap
[_:string]: any,
So, StringMap
has an "index signature" if I'm not mistaken, and isPlainObject
is defined as:
StringMap
isPlainObject
export function isPlainObject(obj: any): obj is object
return isObject(obj) && (
obj.constructor === Object // obj =
So I'd think that the isPlainObject
check would rule out the any
type, and thus values
should necessarily be inferred as StringMap
, but that doesn't appear to be what's happening.
isPlainObject
any
values
StringMap
Even if I make isPlainObject
return obj is StringMap
, Typescript still complains.
isPlainObject
obj is StringMap
How come? Is there any way I can make this work without typecasting everything?
1 Answer
1
Technically, an Array still conforms to the type [key: string]: any
. You can verify this by doing const test: StringMap = ;
. The TypeScript compiler will not complain. So you first have to rule out the possibility that values
is an array.
[key: string]: any
const test: StringMap = ;
values
Next, your function isPlainObject
has the return type defined as obj is object
. That is too generic, and will cause your code block to "forget" that the object has an index signature. It needs to be obj is StringMap
.
isPlainObject
obj is object
obj is StringMap
So in practice, you need to do two things:
if
isPlainObject
obj is StringMap
Basically it will look something like this:
export function isPlainObject(obj: any): obj is StringMap
// ...
export default function formatSql(values: QueryParams)
if (Array.isArray(values))
// ...
else if (isPlainObject(values))
console.log(values[p]);
else
throw new Error(`Unsupported values type`);
I just edited the solution to add more explanation.
– Stefano Dalpiaz
11 hours ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I have to check for array first because arrays are technically objects? Is that why?
– mpen
11 hours ago