Skip to content
This repository was archived by the owner on May 11, 2021. It is now read-only.

Commit 95d80f2

Browse files
committed
Fixed build issues with recursive types and newer versions of TypeScript
1 parent 9d94420 commit 95d80f2

File tree

12 files changed

+1504
-181
lines changed

12 files changed

+1504
-181
lines changed

.changeset/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Changesets
2+
3+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4+
with multi-package repos, or single-package repos to help you version and publish your code. You can
5+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6+
7+
We have a quick list of common questions to get you started engaging with this project in
8+
[our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md)

.changeset/config.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
3+
"changelog": "@changesets/cli/changelog",
4+
"commit": false,
5+
"linked": [],
6+
"access": "public",
7+
"baseBranch": "master"
8+
}

.changeset/four-apricots-arrive.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'typescript-object-validator': minor
3+
---
4+
5+
Fixed build issues with recursive types and newer versions of TypeScript

.github/workflows/ci.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: CI
2+
on: [push, pull_request]
3+
jobs:
4+
run:
5+
name: Run
6+
runs-on: ubuntu-latest
7+
steps:
8+
- uses: actions/checkout@master
9+
10+
- name: Set Node.js 12.x
11+
uses: actions/setup-node@master
12+
with:
13+
node-version: 12.x
14+
15+
- name: yarn install
16+
run: yarn install
17+
18+
- name: Verify
19+
run: yarn verify

.github/workflows/release.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
jobs:
9+
release:
10+
name: Release
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout Repo
14+
uses: actions/checkout@master
15+
16+
- name: Setup Node.js 12.x
17+
uses: actions/setup-node@master
18+
with:
19+
node-version: 12.x
20+
21+
- name: Install Dependencies
22+
run: yarn
23+
24+
- name: Create Release Pull Request or Publish to npm
25+
uses: changesets/action@master
26+
with:
27+
# this expects you to have a script called release which does a build for your packages and calls changeset publish
28+
publish: yarn release
29+
env:
30+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
dist
33
.DS_Store
4+
yarn-error.log

.travis.yml

-20
This file was deleted.

README.md

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Typescript Object Validator
22

3-
[![Build Status](https://travis-ci.com/sevenwestmedia-labs/typescript-object-validator.svg?branch=master)](https://travis-ci.com/sevenwestmedia-labs/typescript-object-validator) [![Greenkeeper badge](https://badges.greenkeeper.io/sevenwestmedia-labs/typescript-object-validator.svg)](https://greenkeeper.io/)
4-
53
A simple library for typescript projects to validating object shapes. You can use this package to declare the shape you'd like an object to align to. This is handy when you have a complex object (for example, an API response) and want to validate the object, AND have typescript recognize the shape.
64

75
## Basic Usage

package.json

+18-12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
{
22
"name": "typescript-object-validator",
3-
"version": "0.0.0",
3+
"version": "1.0.4",
44
"description": "TypeScript first object validator",
55
"main": "dist/cjs/index.js",
66
"module": "dist/esm/index.js",
7+
"types": "dist/cjs/index.d.ts",
78
"sideEffects": false,
89
"scripts": {
910
"prepack": "yarn build",
@@ -12,23 +13,28 @@
1213
"build:cjs": "tsc -p tsconfig.build.json --module commonjs --target es5 --outDir dist/cjs",
1314
"lint": "eslint --ext .js,.ts src",
1415
"test": "jest",
15-
"verify": "yarn tsc -p tsconfig.json && yarn test && yarn lint"
16+
"verify": "yarn tsc -p tsconfig.json && yarn test && yarn lint && yarn build && yarn tsd",
17+
"changeset": "changeset",
18+
"release": "yarn verify && changeset publish"
1619
},
1720
"author": "Jake Ginnivan",
1821
"license": "MIT",
1922
"devDependencies": {
20-
"@types/jest": "^24.0.18",
21-
"@typescript-eslint/eslint-plugin": "^2.3.2",
22-
"@typescript-eslint/parser": "^2.3.2",
23-
"eslint": "^6.5.1",
24-
"eslint-config-prettier": "^6.3.0",
25-
"eslint-config-wanews-base": "^2.0.2",
23+
"@changesets/cli": "^2.4.1",
24+
"@types/jest": "^24.9.0",
25+
"@typescript-eslint/eslint-plugin": "^2.17.0",
26+
"@typescript-eslint/parser": "^2.17.0",
27+
"eslint": "^6.8.0",
28+
"eslint-config-prettier": "^6.9.0",
29+
"eslint-config-wanews-base": "^2.1.1",
2630
"jest": "^24.9.0",
27-
"ts-jest": "^24.1.0",
31+
"ts-jest": "^24.3.0",
32+
"tsd": "^0.11.0",
2833
"tslib": "^1.10.0",
29-
"typescript": "^3.6.3"
34+
"typescript": "^3.7.5"
3035
},
3136
"peerDependencies": {
3237
"tslib": "^1.10.0"
33-
}
34-
}
38+
},
39+
"dependencies": {}
40+
}

src/index.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export type ValidatedType<
1616
: O extends Array<'boolean'>
1717
? boolean[] | undefined
1818
: O extends ObjectShape<O>
19-
? { [key in keyof O]: ValidatedType<O[key]> } | undefined
19+
? MapObjectShape<O> | undefined
2020
: O extends Array<infer U>
2121
? U extends ObjectShape<T>
2222
? Array<{ [key in keyof U]: ValidatedType<U[key]> }> | undefined
@@ -44,6 +44,10 @@ export type ValidatedType<
4444
: unknown
4545
: unknown
4646

47+
type MapObjectShape<T extends ObjectShape<T>> =
48+
| { [key in keyof T]: ValidatedType<T[key]> }
49+
| undefined
50+
4751
export interface ValidationOptions {
4852
/**
4953
* When the type should be an array, if a value is found, but would
@@ -87,8 +91,8 @@ export const validationTypes = {
8791
// We need this generic type so we can merge ObjectShapes and not lose info
8892
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
8993
// @ts-ignore
90-
export interface ObjectShape<T> {
91-
[key: string]: ValidationKeyType<T> | OptionalShape<T>
94+
export type ObjectShape<T extends {}> = {
95+
[key in keyof T]: ValidationKeyType<T[key]> | OptionalShape<T[key]>
9296
}
9397

9498
export type ValidationResult<
@@ -114,7 +118,7 @@ export function optional<T extends ValidationKeyType<T>>(
114118
}
115119
}
116120

117-
export function validateObjectShape<T extends ObjectShape<object>>(
121+
export function validateObjectShape<T extends ObjectShape<T>>(
118122
objectDescription: string,
119123
validationItem: unknown,
120124
expectedObjectShape: T,
@@ -140,7 +144,7 @@ export function validateObjectShape<T extends ObjectShape<object>>(
140144
Object.keys(expectedObjectShape).forEach(expectedKey => {
141145
try {
142146
const actualValue = validationItem[expectedKey]
143-
const expectedType = expectedObjectShape[expectedKey]
147+
const expectedType = (expectedObjectShape as any)[expectedKey]
144148

145149
if (isOptional(expectedType)) {
146150
if (actualValue === undefined) {

test-d/index.test-d.ts

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { expectType } from 'tsd'
2+
3+
import { validateObjectShape, arrayOf, optional } from '../src'
4+
5+
interface SimpleResultType {
6+
one: string
7+
two: number
8+
three: boolean
9+
four: string[]
10+
five: boolean[]
11+
six: number[]
12+
seven: unknown
13+
eight: string | undefined
14+
}
15+
const simpleResult = validateObjectShape(
16+
'Test obj',
17+
{
18+
one: 'string value',
19+
two: 2,
20+
three: true,
21+
four: ['1', '2'],
22+
five: [true, false],
23+
six: [1, 2],
24+
seven: 'whatever'
25+
},
26+
{
27+
one: 'string',
28+
two: 'number',
29+
three: 'boolean',
30+
four: arrayOf('string'),
31+
five: arrayOf('boolean'),
32+
six: arrayOf('number'),
33+
seven: 'unknown',
34+
eight: optional('string')
35+
}
36+
)
37+
38+
if (simpleResult.valid) {
39+
expectType<SimpleResultType>(simpleResult.result)
40+
}
41+
42+
interface NestedResultType {
43+
nested: {
44+
one: string
45+
two: number
46+
three: boolean
47+
four: string[]
48+
five: boolean[]
49+
six: number[]
50+
seven: unknown
51+
}
52+
}
53+
const nestedResult = validateObjectShape(
54+
'Test obj',
55+
{
56+
nested: {
57+
one: 'string value',
58+
two: 2,
59+
three: true,
60+
four: ['1', '2'],
61+
five: [true, false],
62+
six: [1, 2],
63+
seven: 'whatever'
64+
}
65+
},
66+
{
67+
nested: {
68+
one: 'string',
69+
two: 'number',
70+
three: 'boolean',
71+
four: arrayOf('string'),
72+
five: arrayOf('boolean'),
73+
six: arrayOf('number'),
74+
seven: 'unknown'
75+
}
76+
}
77+
)
78+
79+
if (nestedResult.valid) {
80+
expectType<NestedResultType>(nestedResult.result)
81+
}

0 commit comments

Comments
 (0)