Skip to content
This repository has been archived by the owner on Feb 20, 2020. It is now read-only.

fix(sub-type): should transform correctly #33

Merged
merged 1 commit into from
Aug 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/__tests__/__snapshots__/parse.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ declare const v_object: {
readonly [index: number]: any;
};
declare const v_sub_1: X[any][\\"abc\\"][123];
declare const v_sub_2: A.B.C[X[any]][any][any];
declare const v_sub_2: A.B.C[X[any]][any];
declare const v_tuple: [string, number];
declare const v_typeof_1: typeof X;
declare const v_typeof_2: typeof X.Y.Z;
Expand Down Expand Up @@ -186,5 +186,6 @@ type TP<T> = T | string;
type adjust = <T, U>(fn: (v: T) => U, index: number, array: T[]) => (T | U)[];
declare function x<T>(v: T): T;
import xyz = require(\\"xyz\\");
type X = A[B[C]];
"
`;
2 changes: 2 additions & 0 deletions src/__tests__/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ type adjust = <T, U>(fn: (v: T) => U, index: number, array: T[]) => (T | U)[];
declare function x<T>(v: T): T;

import xyz = require('xyz');

type X = A[B[C]];
`;

it('should return correctly', () => {
Expand Down
13 changes: 4 additions & 9 deletions src/parsers/indexed-access-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@ import { create_sub_type, ISubType } from '../types/sub-type';

export const parse_indexed_access_type = (
node: ts.IndexedAccessTypeNode,
): ISubType => {
const types = [node.objectType, node.indexType];
while (types[types.length - 1].kind === ts.SyntaxKind.IndexedAccessType) {
const last_type = types[types.length - 1] as ts.IndexedAccessTypeNode;
types.push(last_type.indexType);
}
return create_sub_type({
types: types.map(parse_native),
): ISubType =>
create_sub_type({
object: parse_native(node.objectType),
index: parse_native(node.indexType),
});
};
4 changes: 3 additions & 1 deletion src/types/__tests__/__snapshots__/sub-type.ts.snap
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should return correctly 1`] = `"any[string][number]"`;
exports[`should return correctly with object 1`] = `"string[any]"`;

exports[`should return correctly with object and index 1`] = `"any[string][number]"`;
10 changes: 4 additions & 6 deletions src/types/__tests__/mapped-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,10 @@ it('should return correctly with parameter, optional, readonly, type', () => {
optional: true,
readonly: true,
type: create_sub_type({
types: [
in_type,
create_general_type({
name: parameter.name,
}),
],
object: in_type,
index: create_general_type({
name: parameter.name,
}),
}),
}),
),
Expand Down
22 changes: 15 additions & 7 deletions src/types/__tests__/sub-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,38 @@ import { any_type, number_type, string_type } from '../../constants';
import { emit } from '../../emit';
import { create_sub_type, is_sub_type } from '../sub-type';

it('should return correctly', () => {
it('should return correctly with object', () => {
expect(
emit(
create_sub_type({
types: [any_type, string_type, number_type],
object: string_type,
}),
),
).toMatchSnapshot();
});

it('should throw error with types (length < 2)', () => {
expect(() =>
it('should return correctly with object and index', () => {
expect(
emit(
create_sub_type({
types: [],
object: create_sub_type({
object: any_type,
index: string_type,
}),
index: number_type,
}),
),
).toThrowError();
).toMatchSnapshot();
});

describe('is_sub_type', () => {
it('should return correctly', () => {
const element = create_sub_type({
types: [any_type, string_type, number_type],
object: create_sub_type({
object: any_type,
index: string_type,
}),
index: number_type,
});
expect(is_sub_type(element)).toBe(true);
});
Expand Down
29 changes: 8 additions & 21 deletions src/types/sub-type.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as ts from 'typescript';
import { IType } from '../collections';
import { ElementKind } from '../constants';
import { any_type, ElementKind } from '../constants';
import {
create_element,
is_element,
Expand All @@ -10,7 +10,8 @@ import {
import { transform } from '../transform';

export interface ISubTypeOptions extends IElementOptions {
types: IType[];
object: IType;
index?: IType;
}

export interface ISubType
Expand All @@ -28,22 +29,8 @@ export const is_sub_type = (value: any): value is ISubTypeOptions =>
/**
* @hidden
*/
export const transform_sub_type = (
element: ISubType,
path: IElement<any>[],
) => {
const minimum_length_of_types = 2;
if (element.types.length < minimum_length_of_types) {
throw new Error(
`sub_type.types.length should >= ${minimum_length_of_types}`,
);
}
const types = element.types.map(type => transform(type, path) as ts.TypeNode);
return types
.slice(minimum_length_of_types)
.reduce(
(parent_type, sub_type) =>
ts.createIndexedAccessTypeNode(parent_type, sub_type),
ts.createIndexedAccessTypeNode(types[0], types[1]),
);
};
export const transform_sub_type = (element: ISubType, path: IElement<any>[]) =>
ts.createIndexedAccessTypeNode(
transform(element.object, path) as ts.TypeNode,
transform(element.index || any_type, path) as ts.TypeNode,
);