Skip to content

Instantly share code, notes, and snippets.

@aaronjensen
Created February 3, 2017 19:09
Show Gist options
  • Save aaronjensen/84d98daddf067781a176590955f258b1 to your computer and use it in GitHub Desktop.
Save aaronjensen/84d98daddf067781a176590955f258b1 to your computer and use it in GitHub Desktop.
export class Endpoint<TResponse> {
url: string
method: RequestMethod
constructor({ url, query = {}, method = 'GET' }: RequestProps) {
const qs = queryString.stringify(query)
this.url = qs ? `${url}?${qs}` : url
this.method = method
}
}
export const getIndustriesRequest: Endpoint<IndustriesResponse> =
new Endpoint({ url: industriesUrl() })
export type FetchFulfilledResponse<TResponse> = Exact<{
request: Endpoint<TResponse>,
response: TResponse,
}>
@gcanti
Copy link

gcanti commented Feb 4, 2017

TypeScript's type system being structural, I think that the only chance to encode phantom types is with "phantom class properties"

type RequestMethod = 'GET' | 'POST'
type RequestProps = { url: string, query?: Object, method?: RequestMethod }
declare var queryString: any

type IndustriesResponse = { name: string };

export class Endpoint<TResponse> {
  private readonly _TResponse: TResponse; // <= phantom class property, never assigned, is here only for type checking
  url: string;
  method: RequestMethod;
  constructor({ url, query = {}, method = 'GET' }: RequestProps) {
    const qs = queryString.stringify(query)
    this.url = qs ? `${url}?${qs}` : url
    this.method = method
  }
}

export const getIndustriesRequest = new Endpoint<IndustriesResponse>({ url: 'url1' })

export type FetchFulfilledResponse<TResponse> = {
  request: Endpoint<TResponse>,
  response: TResponse,
}

// error: Type 'IndustriesResponse' is not assignable to type 'string'
const r1: FetchFulfilledResponse<string> = {
  request: getIndustriesRequest,
  response: 'a'
}

// error: Type 'string' is not assignable to type 'IndustriesResponse'
const r2: FetchFulfilledResponse<IndustriesResponse> = {
  request: getIndustriesRequest,
  response: 'a'
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment