From d3aa7f7578ebbc36a84acd0b4a06de51dc94bdc2 Mon Sep 17 00:00:00 2001 From: denis Date: Wed, 7 Mar 2018 23:34:04 +0100 Subject: [PATCH] Improve topojson types Remove all `any` Add tests Activate StrictNullChecks --- types/topojson/index.d.ts | 216 ++++++++++++++++++--- types/topojson/test/atlas-tests.ts | 66 +++++++ types/topojson/test/client-tests.ts | 97 +++++++++ types/topojson/test/server-tests.ts | 14 ++ types/topojson/test/simplify-tests.ts | 92 +++++++++ types/topojson/test/specification-tests.ts | 196 +++++++++++++++++++ types/topojson/topojson-tests.ts | 8 +- types/topojson/tsconfig.json | 9 +- 8 files changed, 667 insertions(+), 31 deletions(-) create mode 100644 types/topojson/test/atlas-tests.ts create mode 100644 types/topojson/test/client-tests.ts create mode 100644 types/topojson/test/server-tests.ts create mode 100644 types/topojson/test/simplify-tests.ts create mode 100644 types/topojson/test/specification-tests.ts diff --git a/types/topojson/index.d.ts b/types/topojson/index.d.ts index 67f71310d0..6330f23b1c 100644 --- a/types/topojson/index.d.ts +++ b/types/topojson/index.d.ts @@ -1,49 +1,217 @@ -// Type definitions for topojson 3.0 +// Type definitions for topojson 3.2 // Project: https://github.com/topojson/topojson // Definitions by: Ricardo Mello -// Zhutian Chen +// Zhutian Chen +// denisname // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.5 -export function bbox(topology: any): any; +import * as GeoJSON from "geojson"; -export function feature(topology: any, o: any): { features: any[]; type: string }; +export as namespace topojson; -export function filter(topology: any, filter: any): any; +// --------------------------------------------------------------- +// TopoJSON Format Specification +// --------------------------------------------------------------- -export function filterAttached(topology: any): any; +// See: https://github.com/topojson/topojson-specification/ -export function filterAttachedWeight(topology: any, minWeight: any, weight: any): any; +// 2. TopoJSON Objects +export interface TopoJSON { + type: "Topology" | GeoJSON.GeoJsonGeometryTypes | null; + bbox?: GeoJSON.BBox; +} -export function filterWeight(topology: any, minWeight: any, weight: any): any; +// 2.1. Topology Objects +export interface Topology = Objects> extends TopoJSON { + type: "Topology"; + objects: T; + arcs: Arc[]; + transform?: Transform; +} -export function merge(topology: any, ...args: any[]): { type: any, coordinates: any[] }; +// 2.1.1. Positions +export type Positions = number[]; // at least two elements -export function mergeArcs(topology: any, objects: any): any; +// 2.1.2. Transforms +export interface Transform { + scale: [number, number]; + translate: [number, number]; +} -export function mesh(topology: any, ...args: any[]): { type: any; coordinates: any[]; }; +// 2.1.3. Arcs +export type Arc = Positions[]; // at least two elements -export function meshArcs(topology: any, object$$1: any, filter: any, ...args: any[]): { type: any; coordinates: any[]; }; +// 2.1.4. Arc Indexes +export type ArcIndexes = number[]; -export function neighbors(objects: any): any[]; +// 2.1.5. Objects +export type Properties = GeoJSON.GeoJsonProperties; -export function planarRingArea(ring: any): any; +export interface Objects

{ + [key: string]: GeometryObject

; +} -export function planarTriangleArea(triangle: any): any; +// 2.2. Geometry Objects +export interface GeometryObjectA

extends TopoJSON { + type: GeoJSON.GeoJsonGeometryTypes | null; + id?: number | string; + properties?: P; +} -export function presimplify(topology: any, weight: any): any[]; +export type GeometryObject

= + Point

| MultiPoint

| + LineString

| MultiLineString

| + Polygon

| MultiPolygon

| + GeometryCollection

| + NullObject; -export function quantile(topology: any, p: any): any; +// 2.2.1. Point +export interface Point

extends GeometryObjectA

{ + type: "Point"; + coordinates: Positions; +} -export function quantize(topology: any, transform: any): any; +// 2.2.2. MultiPoint +export interface MultiPoint

extends GeometryObjectA

{ + type: "MultiPoint"; + coordinates: Positions[]; +} -export function simplify(topology: any, minWeight: any): any; +// 2.2.3. LineString +export interface LineString

extends GeometryObjectA

{ + type: "LineString"; + arcs: ArcIndexes; +} -export function sphericalRingArea(ring: any, interior: any): any; +// 2.2.4. MultiLineString +export interface MultiLineString

extends GeometryObjectA

{ + type: "MultiLineString"; + arcs: ArcIndexes[]; +} -export function sphericalTriangleArea(t: any): any; +// 2.2.5. Polygon +export interface Polygon

extends GeometryObjectA

{ + type: "Polygon"; + arcs: ArcIndexes[]; +} -export function topology(objects: any, quantization: any): any; +// 2.2.6. MultiPolygon +export interface MultiPolygon

extends GeometryObjectA

{ + type: "MultiPolygon"; + arcs: ArcIndexes[][]; +} -export function transform(transform: any): any; +// 2.2.7. Geometry Collection +export interface GeometryCollection

extends GeometryObjectA

{ + type: "GeometryCollection"; + geometries: Array>; +} -export function untransform(transform: any): any; +// More +export interface NullObject extends GeometryObjectA { + type: null; +} + +export type OrNull = { + [P in keyof T]: T[P] | NullObject; +}; + +// --------------------------------------------------------------- +// TopoJSON Server +// --------------------------------------------------------------- + +export function topology(objects: {[k: string]: GeoJSON.GeoJsonObject}, quantization?: number): Topology; + +// --------------------------------------------------------------- +// TopoJSON Simplify +// --------------------------------------------------------------- + +export type Triangle = [[number, number], [number, number], [number, number]]; +export type TriangleWeighter = (triangle: Triangle) => number; +export type Ring = Array<[number, number]>; +export type RingWeighter = (triangle: Ring) => number; +export type Filter = (ring: Ring, interior: boolean) => boolean; + +export function presimplify(topology: Topology, weight?: TriangleWeighter): Topology; + +export function simplify(topology: Topology, minWeight?: number): Topology; + +export function quantile(topology: Topology, p: number): number; + +export function filter(topology: Topology, filter: Filter): Topology>; + +export function filterAttached(topology: Topology): Filter; + +export function filterAttachedWeight(topology: Topology, minWeight?: number, weight?: RingWeighter): Filter; + +export function filterWeight(topology: Topology, minWeight?: number, weight?: RingWeighter): Filter; + +export function planarRingArea(ring: Ring): number; + +export function planarTriangleArea(triangle: Triangle): number; + +export function sphericalRingArea(ring: Ring, interior: true): number; + +export function sphericalTriangleArea(triangle: Triangle): number; + +// --------------------------------------------------------------- +// TopoJSON Client +// --------------------------------------------------------------- + +export type Transformer = (point: number[], index?: boolean) => number[]; + +export function feature

(topology: Topology, object: Point

): GeoJSON.Feature; +export function feature

(topology: Topology, object: MultiPoint

): GeoJSON.Feature; +export function feature

(topology: Topology, object: LineString

): GeoJSON.Feature; +export function feature

(topology: Topology, object: MultiLineString

): GeoJSON.Feature; +export function feature

(topology: Topology, object: Polygon

): GeoJSON.Feature; +export function feature

(topology: Topology, object: MultiPolygon

): GeoJSON.Feature; +export function feature

(topology: Topology, object: GeometryCollection

): GeoJSON.FeatureCollection; +export function feature

(topology: Topology, object: GeometryObject

) + : GeoJSON.Feature | GeoJSON.FeatureCollection; + +export function merge(topology: Topology, objects: Array): GeoJSON.MultiPolygon; + +export function mergeArcs(topology: Topology, objects: Array): MultiPolygon; + +export function mesh(topology: Topology, obj?: GeometryObject, filter?: (a: GeometryObject, b: GeometryObject) => boolean): GeoJSON.MultiLineString; + +export function meshArcs(topology: Topology, obj?: GeometryObject, filter?: (a: GeometryObject, b: GeometryObject) => boolean): MultiLineString; + +export function neighbors(objects: GeometryObject[]): number[][]; + +export function bbox(topology: Topology): GeoJSON.BBox; + +export function quantize(topology: Topology, transform: Transform | number): Topology; + +export function transform(transform: Transform | null): Transformer; + +export function untransform(transform: Transform | null): Transformer; + +// --------------------------------------------------------------- +// U.S. Atlas TopoJSON +// --------------------------------------------------------------- + +export interface UsAtlas extends topojson.Topology { + objects: { + counties: {type: "GeometryCollection", geometries: Array}; + states: {type: "GeometryCollection", geometries: Array}; + nation: topojson.GeometryCollection; + }; + bbox: [number, number, number, number]; + transform: topojson.Transform; +} + +// --------------------------------------------------------------- +// World Atlas TopoJSON +// --------------------------------------------------------------- + +export interface WorldAtlas extends topojson.Topology { + objects: { + countries: {type: "GeometryCollection", geometries: Array}; + land: topojson.GeometryCollection; + }; + bbox: [number, number, number, number]; + transform: topojson.Transform; +} diff --git a/types/topojson/test/atlas-tests.ts b/types/topojson/test/atlas-tests.ts new file mode 100644 index 0000000000..3cbb9c12f2 --- /dev/null +++ b/types/topojson/test/atlas-tests.ts @@ -0,0 +1,66 @@ +// Tests for: https://github.com/topojson/us-atlas and https://github.com/topojson/world-atlas + +const world: topojson.WorldAtlas = { + type: "Topology", + objects: { + countries: { + type: "GeometryCollection", + geometries: [{ + type: "Polygon", + arcs: [[]], + id: "004", + }], + }, + land: { + type: "GeometryCollection", + geometries: [{ + type: "MultiPolygon", + arcs: [[[]]], + }], + }, + }, + arcs: [[]], + bbox: [-180, -85, 180, 83], + transform: { + scale: [0, 0], + translate: [-180, -85], + }, +}; + +const us: topojson.UsAtlas = { + type: "Topology", + bbox: [-56, 12, 942, 596], + transform: { + scale: [0, 0], + translate: [-56, 12], + }, + objects: { + counties: { + type: "GeometryCollection", + geometries: [{ + type: "Polygon", + arcs: [[]], + id: "05089", + }], + }, + states: { + type: "GeometryCollection", + geometries: [{ + type: "MultiPolygon", + arcs: [[[]]], + id: "11", + }], + }, + nation: { + type: "GeometryCollection", + geometries: [{ + type: "MultiPolygon", + arcs: [[[]]], + }], + }, + }, + arcs: [[[]]], +}; + +// $ExpectError +us.objects.xxx; diff --git a/types/topojson/test/client-tests.ts b/types/topojson/test/client-tests.ts new file mode 100644 index 0000000000..2e21e2b665 --- /dev/null +++ b/types/topojson/test/client-tests.ts @@ -0,0 +1,97 @@ +// Tests for: https://github.com/topojson/topojson-client + +let geoMP: GeoJSON.MultiPolygon; +let geoMLS: GeoJSON.MultiLineString; +let topoMP: topojson.MultiPolygon; +let topoMLS: topojson.MultiLineString; +let bbox: GeoJSON.BBox; +let transformer: topojson.Transformer; +let color: string; +let size: number; + +interface TestProp { + color: string; + size: number; +} + +const selectedGeometries: Array = + us.objects.states.geometries.filter((g) => ["be", 2, undefined].indexOf(g.id) >= 0); + +const topoWithProp = { + type: "Topology" as "Topology", + transform: {scale: [1, 1] as [number, number], translate: [0, 0] as [number, number]}, + objects: { + foo: {type: "Polygon" as "Polygon", properties: {color: "orange", size: 42}, arcs: [[0]]}, + bar: {type: "Polygon" as "Polygon", properties: {name: "hello"}, arcs: [[0]]}, + more: {type: "Polygon" as "Polygon", arcs: [[0]]}, + coll: { + type: "GeometryCollection" as "GeometryCollection", geometries: [ + {type: "Polygon" as "Polygon", properties: {color: "orange", size: 42}, arcs: [[0]]}, + ], + }, + }, + arcs: [ + [[0, 0], [1, 0], [0, 1], [-1, 0], [0, -1]], + [[0, 0], [1, 0], [0, 1]], + [[1, 1], [-1, 0], [0, -1]], + [[1, 1]], + [[0, 0]] + ], +}; + +const featurePolygon: GeoJSON.Feature = + topojson.feature(topoWithProp, topoWithProp.objects.foo); + +const featurePolygonWithProp: GeoJSON.Feature = + topojson.feature(topoWithProp, topoWithProp.objects.foo); + +const featureCollection: GeoJSON.FeatureCollection = + topojson.feature(us, us.objects.counties); + +const featureObject: GeoJSON.Feature | GeoJSON.FeatureCollection = + topojson.feature(topoWithProp, topoWithProp.objects.foo as topojson.GeometryObject); + +const propColor = topojson.feature(topoWithProp, topoWithProp.objects.foo).properties; +color = propColor.color; +size = propColor.size; + +const propName = topojson.feature(topoWithProp, topoWithProp.objects.bar).properties; +const aName: string = propName.name; + +const propCollection = topojson.feature(topoWithProp, topoWithProp.objects.coll).features[0].properties; +color = propCollection.color; +size = propCollection.size; + +const prop3: GeoJSON.GeoJsonProperties = topojson.feature(topoWithProp, topoWithProp.objects.more).properties; + +geoMP = topojson.merge(us, selectedGeometries); + +topoMP = topojson.mergeArcs(us, selectedGeometries); + +geoMLS = topojson.mesh(us); +geoMLS = topojson.mesh(us, us.objects.states); +geoMLS = topojson.mesh(us, us.objects.states, (a, b) => a !== b); + +topoMLS = topojson.meshArcs(us); +topoMLS = topojson.meshArcs(us, us.objects.states); +topoMLS = topojson.meshArcs(us, us.objects.states, (a, b) => a !== b); + +const n: number[][] = topojson.neighbors(world.objects.countries.geometries); + +// Transforms +const usTransform: topojson.Transform = us.transform; + +bbox = topojson.bbox(us); +bbox = topojson.bbox({type: "Topology", objects: {}, arcs: []}); + +newUs = topojson.quantize(us, 1e4); +newUs = topojson.quantize(us, {scale: [1, 1], translate: [0, 0]}); +newUs = topojson.quantize(us, us.transform); + +transformer = topojson.transform(null); +transformer = topojson.transform({scale: [1, 1], translate: [0, 0]}); +transformer = topojson.transform(usTransform); + +transformer = topojson.untransform(null); +transformer = topojson.untransform({scale: [1, 1], translate: [0, 0]}); +transformer = topojson.untransform(usTransform); diff --git a/types/topojson/test/server-tests.ts b/types/topojson/test/server-tests.ts new file mode 100644 index 0000000000..262fa8e6f5 --- /dev/null +++ b/types/topojson/test/server-tests.ts @@ -0,0 +1,14 @@ +// Tests for: https://github.com/topojson/topojson-server + +let topo: topojson.Topology; + +const aPoint: GeoJSON.Point = {type: "Point", coordinates: [30, 10]}; +const aPolygon: GeoJSON.Polygon = {type: "Polygon", coordinates: [[[30, 10], [40, 40], [20, 40], [30, 10]]]}; + +const objects = { + aPoint, + aPolygon, +}; + +topo = topojson.topology(objects); +topo = topojson.topology(objects, 1e4); diff --git a/types/topojson/test/simplify-tests.ts b/types/topojson/test/simplify-tests.ts new file mode 100644 index 0000000000..6347466236 --- /dev/null +++ b/types/topojson/test/simplify-tests.ts @@ -0,0 +1,92 @@ +// Tests for: https://github.com/topojson/topojson-simplify + +interface UsAtlasObjects extends topojson.Objects { + counties: {type: "GeometryCollection", geometries: Array}; + states: {type: "GeometryCollection", geometries: Array}; + nation: topojson.GeometryCollection; +} + +interface UsEmpty extends topojson.Objects { + counties: topojson.NullObject; + states: topojson.NullObject; + nation: topojson.NullObject; +} + +let aTopology: topojson.Topology; +let presimplifiedUs: topojson.Topology; +let newUs: topojson.Topology; +let emptyUs: topojson.Topology; +let geomCollection: topojson.GeometryCollection; +let geomCollectionOrNull: topojson.GeometryCollection | topojson.NullObject; +let aNullObject: topojson.NullObject; +let filter: topojson.Filter; + +presimplifiedUs = topojson.presimplify(us); +presimplifiedUs = topojson.presimplify(us, topojson.planarTriangleArea); +presimplifiedUs = topojson.presimplify(us, topojson.sphericalTriangleArea); +presimplifiedUs = topojson.presimplify(us, (points: Array<[number, number]>) => 1.5); + +geomCollection = topojson.presimplify(us).objects.counties; +geomCollection = topojson.presimplify(us).objects.nation; +geomCollection = topojson.presimplify(us).objects.states; + +let minWeight = topojson.quantile(presimplifiedUs, 0.5); + +newUs = topojson.simplify(presimplifiedUs); +newUs = topojson.simplify(presimplifiedUs, 1.23); +newUs = topojson.simplify(presimplifiedUs, minWeight); + +geomCollection = topojson.simplify(presimplifiedUs).objects.counties; +geomCollection = topojson.simplify(presimplifiedUs).objects.nation; +geomCollection = topojson.simplify(presimplifiedUs).objects.states; + +// Filtering + +filter = topojson.filterAttached(us); + +filter = topojson.filterAttachedWeight(us); +filter = topojson.filterAttachedWeight(us, 0.5); +filter = topojson.filterAttachedWeight(us, 0.5, topojson.planarRingArea); +filter = topojson.filterAttachedWeight(us, 0.5, (points: Array<[number, number]>) => 1.5); + +filter = topojson.filterWeight(us); +filter = topojson.filterWeight(us, 0.5); +filter = topojson.filterWeight(us, 0.5, topojson.planarRingArea); +filter = topojson.filterWeight(us, 0.5, (points: Array<[number, number]>) => 1.5); + +aTopology = topojson.filter(us, filter); +newUs = topojson.filter(us, (ring: topojson.Ring, interior: boolean) => true) as topojson.UsAtlas; +emptyUs = topojson.filter(us, () => false) as topojson.Topology; + +geomCollectionOrNull = topojson.filter(us, () => Math.random() > 0.9).objects.nation; +aNullObject = topojson.filter(us, () => false).objects.nation as topojson.NullObject; +geomCollection = topojson.filter(us, () => true).objects.nation as topojson.GeometryCollection; + +// Geometry + +let area: number; +area = topojson.planarRingArea([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]); +area = topojson.planarTriangleArea([[0, 0], [0, 1], [1, 1]]); +area = topojson.sphericalRingArea([[0, 0], [0, 90], [90, 180], [0, 0]], true); +area = topojson.sphericalTriangleArea([[0, 0], [0, 90], [90, 180]]); + +// Fails + +interface MyAtlas extends topojson.Topology { + objects: { + obj: topojson.GeometryCollection; + }; + more: "hello"; +} + +let myAtlas: MyAtlas = null as any; // shortcut... +console.log(myAtlas.more); + +let s: string; +// $ExpectError +s = topojson.presimplify(myAtlas).more; // must fail +// $ExpectError +s = topojson.simplify(myAtlas).more; // must fail + +// // $ExpectError +// area = topojson.planarTriangleArea([[0, 0], [0, 1], [1, 1], [1, 0]]); // must fail in 2.7 diff --git a/types/topojson/test/specification-tests.ts b/types/topojson/test/specification-tests.ts new file mode 100644 index 0000000000..ccb4275468 --- /dev/null +++ b/types/topojson/test/specification-tests.ts @@ -0,0 +1,196 @@ +// Tests for: https://github.com/topojson/topojson-specification + +// Geometry Objects + +const point: topojson.Point = { + type: "Point", + coordinates: [0, 0], +}; + +const multiPoint: topojson.MultiPoint = { + type: "MultiPoint", + coordinates: [[0, 0]], +}; + +const lineString: topojson.LineString = { + type: "LineString", + arcs: [0], +}; + +const multiLineString: topojson.MultiLineString = { + type: "MultiLineString", + arcs: [[3], [4]], +}; + +const polygon: topojson.Polygon = { + type: "Polygon", + arcs: [[0]], +}; + +const multiPolygon: topojson.MultiPolygon = { + type: "MultiPolygon", + arcs: [[[0]]], +}; + +const geometryCollection: topojson.GeometryCollection = { + type: "GeometryCollection", + geometries: [ + {type: "Polygon", arcs: [[0]]}, + {type: "MultiPolygon", arcs: [[[0]]]}, + {type: "GeometryCollection", geometries: [ + {type: "Point", coordinates: [0, 0]} + ]} + ], +}; + +const nullObject: topojson.NullObject = { + type: null, +}; + +// Properties + +interface TestProp { + color: string; + size: number; +} + +const pointWithProp: topojson.Point = { + type: "Point", + coordinates: [0, 0], + properties: {color: "orange", size: 42}, +}; + +const str: string = pointWithProp.properties!.color; +const nbr: number = pointWithProp.properties!.size; + +// Topology + +let topology: topojson.Topology; + +topology = { + type: "Topology", + objects: {}, + arcs: [], +}; + +topology = { + type: "Topology", + bbox: [0, 0, 1, 1], + transform: { + scale: [1, 1], + translate: [0, 0], + }, + objects: { + foo: { + type: "Polygon", + arcs: [[0]], + }, + }, + arcs: [[[0, 0], [1, 1]], [[1, 1], [-1, -1]]], +}; + +topology = { + type: "Topology", + transform: { + scale: [1, 1], + translate: [0, 0], + }, + objects: { + point, + lineString, + multiLineString, + multiPoint, + polygon, + multiPolygon, + geometryCollection, + nullObject, + }, + arcs: [ + [[0, 0], [1, 0], [0, 1], [-1, 0], [0, -1]], + [[0, 0], [1, 0], [0, 1]], + [[1, 1], [-1, 0], [0, -1]], + [[1, 1]], + [[0, 0]] + ], +}; + +topology = { + type: "Topology", + objects: { + example: { + type: "GeometryCollection", + geometries: [ + { + type: "Point", + properties: { + prop0: "value0", + }, + coordinates: [102, 0.5], + }, + { + type: "LineString", + properties: { + prop0: "value0", + prop1: 0, + }, + arcs: [0], + }, + { + type: "Polygon", + properties: { + prop0: "value0", + prop1: { + this: "that", + }, + }, + arcs: [[-2]], + } + ], + }, + }, + arcs: [ + [[102, 0], [103, 1], [104, 0], [105, 1]], + [[100, 0], [101, 0], [101, 1], [100, 1], [100, 0]] + ], +}; + +// Fails + +// $ExpectError +topology = { + type: "Topology", + objects: { + foo: { + type: "hello", // must fail + arcs: [[0]], + }, + }, + arcs: [], +}; + +// $ExpectError +topology = { + type: "Topology", + objects: { + foo: { + type: "Point", + // must fail: Property 'coordinates' is missing in type '{ type: "Point"; }'. + }, + }, + arcs: [], +}; + +// $ExpectError +topology = { + type: "Topology", + objects: { + foo: { + type: "GeometryCollection", + geometries: [ + {type: "Polygon"} + // must fail: Property 'arcs' is missing in type '{ type: "Polygon"; }' + ], + }, + }, + arcs: [], +}; diff --git a/types/topojson/topojson-tests.ts b/types/topojson/topojson-tests.ts index 68171809d5..953fda4743 100644 --- a/types/topojson/topojson-tests.ts +++ b/types/topojson/topojson-tests.ts @@ -1,6 +1,4 @@ -import * as topojson from 'topojson'; +const hello = "world"; -// TODO: complete tests. - -topojson.feature(null, null); // $ExpectType { features: any[]; type: string; } -topojson.mesh(null, null, (a: any, b: any) => a !== b); // $ExpectType { type: any; coordinates: any[]; } +// NOTE: The standard bundle definition has no particular function. +// See ./test/ for per bundle tests. diff --git a/types/topojson/tsconfig.json b/types/topojson/tsconfig.json index 339e9a307d..65b6cd1f07 100644 --- a/types/topojson/tsconfig.json +++ b/types/topojson/tsconfig.json @@ -7,7 +7,7 @@ ], "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "strictFunctionTypes": true, "baseUrl": "../", "typeRoots": [ @@ -19,6 +19,11 @@ }, "files": [ "index.d.ts", - "topojson-tests.ts" + "topojson-tests.ts", + "test/atlas-tests.ts", + "test/client-tests.ts", + "test/server-tests.ts", + "test/simplify-tests.ts", + "test/specification-tests.ts" ] } \ No newline at end of file