#Generic as interface key
54 messages · Page 1 of 1 (latest)
Preview:```ts
export type APIResponseStatus = "error" | "success"
export interface APIResponse<
TResponse = any,
TResponseKey extends string = "response"
{
[K: TResponseKey]: TResponse
status: APIResponseStatus
code?: string | null
message?: string
}```
!:index%
Index signatures apply to all members of the type that match the signature. Therefore, the following type is invalid, even though TypeScript does not detect it until you actually try to construct a value which conforms to the type.
type Foo = { a: 1 } & { [x: string]: 2 }
TypeScript does not have a way to specify "everything besides defined keys" since it does not have negated types. This pattern cannot be expressed in TypeScript today. A more TS-friendly version of it puts all of the extra properties on a dedicated key:
type Foo = { a: 1; extra: { [x: string]: 2 } }
negated types: https://github.com/microsoft/TypeScript/pull/29317
but yeah also what the error says, consider using a mapped type instead
you'd want to separate it out though
you could have like, APIResponse<number, "status" | "code" | "message"> and now message should be both a number and a string, that doesn't make sense
having a separated object like in the example there would work, but honestly i feel like you may want to just reconsider the design in general
its just for internal use, its because the api response can have a response or app property and i dont want to repeat the same type and just change the prop name
typescript just breaks when i try this lol
yes, because your type doesn't handle that well
you should constrain your generic key to be "response" | "app" then, not string
but also that means it could have both of them or neither, are you sure that's what you want?
couldnt have neither cause it has a default value
not how it works
actually, no problem having neither or both
APIResponse<unknown, never> is perfectly valid for your type, never does extend string
but is that what you want your type to mean
yes
you do you then. that sounds like a terrible design ngl.
whats ngl?
oh ty
i just want it simple
this is the opposite of simple
wdym?
making it more specific would make it simpler, generics aren't meant for this kind of thing
// both are optional, meaning having neither or both are valid
type APIResponse<T = unknown> = {
response?: T
app?: T
status: APIResponseStatus
code?: string | null
message?: string
};
// specified separately, would require `?: never` keys to ensure exclusivity but it works for literals
type APIResponse<T = unknown> = {
status: APIResponseStatus
code?: string | null
message?: string
} & ({ response: T } | { app: T });
but just in general, having 2 possible result keys seems like code smell to me
didn't you say it was for internal use
eh maybe i just misinterpreted what you meant there, whatever
yes im typing the api for personal use
its just how this api works
yes im typing the api for personal use
so why not just... fix your api
do generics affect performance?
so back to this; just use the type that actually represents how the api works then. don't settle for "no problem"
no, ts doesn't affect runtime performance, that's kind of its thing
but generics affect readability and maintainability
oh yes, forgot that