I\'m trying to write an interface but it keeps popin\' an error:
\"Property \'success\' of type \'boolean\' is not assignable to string index type \'PageableLarave
Unfortunately that isn't allowed with the index signature syntax that you're using. When you add the index signature ([key: string]: PageableLaravel
) that means that all properties must be PageableLaravel, not just all unspecified properties.
You can solve this with an intersection type though:
export interface PageableLaravel {
path: string;
current_page: number;
from: number;
}
export type Pageable = {
success: boolean;
message: string;
} & {
[key: string]: PageableLaravel
}
TypeScript playground demo
There's no concrete type in TypeScript that exactly matches what you're asking for. Maybe one day TypeScript will support arbitrary index signatures and negated types, at which point we'd be able to represent something like a "default" property value. But for now, there are only workarounds.
The intersection type in the other answer is one common workaround which works fairly well for reading properties, but not so much for writing them.
There is, however, a reasonably straightforward generic type that represents the concept of "some unknown other keys":
interface BasePageable {
success: boolean;
message: string;
}
type Pageable<K extends keyof any> = BasePageable &
Record<Exclude<K, keyof BasePageable>, PageableLaravel>;
Here Pageable<K>
is generic in K
, the name(s) of the extra key(s) whose values you want to be PageableLaravel
types. To use this type you might want a helper function so you don't need to manually specify the value of K
:
const asPageable = <P extends Pageable<keyof P>>(p: P) => p;
And here it is in action:
const works = asPageable({
success: true,
message: "hey",
foo: {
path: "x",
current_page: 123,
from: 1
}
});
const flagsImproperValue = asPageable({
success: true,
message: "hey",
foo: 123 // error!
});
// Type 'number' is not assignable to type 'PageableLaravel'.
Note that this does not capture the number of extra keys as exactly one. It allows more than one and less than one:
const allowsExtraKeys = asPageable({
success: true,
message: "hey",
foo: {
path: "x",
current_page: 123,
from: 1
},
bar: {
path: "x",
current_page: 123,
from: 1
}
});
const allowsMissingKeys = asPageable({
success: true,
message: "hey"
});
Of course, your original index signature would have that issue also. The restriction that there be exactly one key in addition to success
and message
is expressible in TypeScript but it is ugly and hard to work with. This is probably good enough for your purposes.
This is still a workaround because it's generic where you might have expected a concrete type. Okay, hope that helps; good luck!
Link to code