The Firebase typings have an interface IQuery
which has the equalTo()
method typed as:
public equalTo(value: number | string | boolean | null, name?: string): IQuery;
I have a mocking library which is trying to mimic the API surface of what Firebase is exposing but in the case of the name
parameter the general typing of "string" can be made more specific:
public equalTo(value: number | string | boolean | null, key?: keyof T): IQuery<T>
By stating keyof T
we get some very useful static checking that I'd hate to lose out on and in fact up to TypeScript 2.8.3 I seemed to be able to do this but when moving to 2.9.x
+ of Typescript I now get this error:
Type 'string' is not assignable to type 'keyof T'.
For a bit more context, the class definition in my mocking library is:
export default class Query<T = any> implements IQuery<T> { ... }
Where the <T>
generic type is an indicator of type of the data structure that the query will return.
Further it is worth noting that T, will always be shaped as a dictionary/hash with string keys and therefore keyof T
will subset of string values but in my typing I'm not making this clear so I get where Typescript is taking issue ... I just don't know how to express that keyof T
must be a string.
keyof is a keyword in TypeScript which is used to extract the key type from an object type.
keyof T returns a union of string literal types. The extends keyword is used to apply constraints to K, so that K is one of the string literal types only. extends means “is assignable” instead of “inherits”' K extends keyof T means that any value of type K can be assigned to the string literal union types.
This is related to a change in the way keyof
works in 2.9, until 2.9 keyof
only returned string
keys, from 2.9 onward it will return number
and symbol
keys. This is the reference for this
To only accept string
keys you can use Extract<keyof T, string>
as the type for the key
parameter, or if you want to revert to the old behavior you can use the --keyofStringsOnly
compiler flag
public equalTo(value: number | string | boolean | null, key?: Extract<keyof T, string>): IQuery<T>
You can also require keys in your type to be string-only:
key?: keyof T & string
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With