I have an object with conditional keys. I.e.:
const headers: RequestHeaders = {};
if (...) {
headers.foo = 'foo';
}
if (...) {
headers.bar = 'bar';
}
I'm new to TS and I expected this to work:
type RequestHeaders = {
foo?: string,
bar?: string,
};
However, I'm passing this to fetch
and the type definition for fetch
's headers is { [key: string]: string }
. I'm getting:
Type 'RequestHeaders' is not assignable to type '{ [key: string]: string; }'.
Property 'foo' is incompatible with index signature.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
The only way I could get this to work is type RequestHeaders = { [key: string]: string };
. Is there a way to limit the keys to a set of predefined strings?
The fetch API does not accept a headers object that has a key with an undefined value. Since each of your optional types can be either string | undefined
, the compiler is rejecting them.
Here is an approach that filters the headers to remove those with undefined values. Its type predicate (is
) keeps the compiler happy.
const buildHeaders = (requestHeaders: RequestHeaders): HeadersInit =>
Object.entries(requestHeaders).filter(
(entry): entry is [string, string] => entry[1] !== undefined
);
const headers: RequestHeaders = {};
type RequestHeaders = {
foo?: string; // optional
bar?: string; // optional
baz: string; // required!
};
fetch("Some Data", {
headers: buildHeaders(headers)
});
The advantage of this approach is that it lets you limit the keys to a set of predefined strings while also letting you to specify whether each is required or optional.
The header data of fetch
method must be type like
type HeadersInit = Headers | string[][] | Record<string, string>;
For your case, I think you will define headers
type as a alias of Record<string, string>
. For keys configuration (foo
, bar
), I will have a suggestion: Fixed header keys. Then, you will define all header keys to a type like:
type HeaderKeys = 'foo' | 'bar';
type RequestHeaders = Record<HeaderKeys, string>; // the same: type RequestHeaders = Record<'foo' | 'bar', string>;
const headers: RequestHeaders = {} as RequestHeaders; // force cast
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