Skip to content
Permalink
Browse files

Improve type system for get and head methods (#87)

Fixes #85


Co-authored-by: Szymon Marczak <36894700+szmarczak@users.noreply.github.com>
  • Loading branch information...
2 people authored and sindresorhus committed Feb 22, 2019
1 parent cd33a63 commit 66ea8a7aee7a652eed1f7a7aa3e01d72c57d29a3
Showing with 32 additions and 3 deletions.
  1. +13 −3 index.d.ts
  2. +4 −0 index.js
  3. +11 −0 index.test-d.ts
  4. +4 −0 test/main.js
@@ -1,3 +1,5 @@
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

type JSONObject = {[key: string]: JSONValue};
interface JSONArray extends Array<JSONValue> {}
export type JSONValue = string | number | boolean | null | JSONObject | JSONArray;
@@ -76,6 +78,14 @@ export interface Options extends RequestInit {
throwHttpErrors?: boolean;
}

interface OptionsWithoutBody extends Omit<Options, 'body'> {
method?: 'get' | 'head'
}

interface OptionsWithBody extends Options {
method?: 'post' | 'put' | 'delete'
}

/**
* Returns a `Response` object with `Body` methods added for convenience.
*/
@@ -127,15 +137,15 @@ export interface Ky {
* @param input - `Request` object, `URL` object, or URL string.
* @returns Promise with `Body` method added.
*/
(input: Request | URL | string, options?: Options): ResponsePromise;
(input: Request | URL | string, options?: OptionsWithoutBody | OptionsWithBody): ResponsePromise;

/**
* Fetches the `input` URL with the option `{method: 'get'}`.
*
* @param input - `Request` object, `URL` object, or URL string.
* @returns Promise with `Body` method added.
*/
get(input: Request | URL | string, options?: Options): ResponsePromise;
get(input: Request | URL | string, options?: Omit<Options, 'body'>): ResponsePromise;

/**
* Fetches the `input` URL with the option `{method: 'post'}`.
@@ -167,7 +177,7 @@ export interface Ky {
* @param input - `Request` object, `URL` object, or URL string.
* @returns Promise with `Body` method added.
*/
head(input: Request | URL | string, options?: Options): ResponsePromise;
head(input: Request | URL | string, options?: Omit<Options, 'body'>): ResponsePromise;

/**
* Fetches the `input` URL with the option `{method: 'delete'}`.
@@ -194,6 +194,10 @@ class Ky {
const headers = new Headers(this._options.headers || {});

if (json) {
if (this._options.body) {
throw new Error('The `json` option cannot be used with the `body` option');
}

headers.set('content-type', 'application/json');
this._options.body = JSON.stringify(json);
}
@@ -23,11 +23,22 @@ const requestMethods = [
'delete'
];

const requestBodyMethods = [
'post',
'put',
'delete'
];

// Test Ky HTTP methods
requestMethods.map(async key => {
expectType<ResponsePromise>(await ky[key](server.url));
});

// Test Ky HTTP methods with bodies
requestBodyMethods.map(async key => {
expectType<ResponsePromise>(await ky[key](server.url, {body: 'x'}));
});

expectType<Ky>(ky.extend({}));
expectType<HTTPError>(new HTTPError());
expectType<TimeoutError>(new TimeoutError);
@@ -108,6 +108,10 @@ test('POST JSON', async t => {
await server.close();
});

test('cannot use `json` option along with the `body` option', t => {
t.throws(() => ky('https://example.com', {json: {foo: 'bar'}, body: 'foobar'}), 'The `json` option cannot be used with the `body` option');
});

test('custom headers', async t => {
const server = await createTestServer();
server.get('/', (request, response) => {

0 comments on commit 66ea8a7

Please sign in to comment.
You can’t perform that action at this time.