Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Convert to TypeScript and ensure strict type safety #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
XDGFX wants to merge 11 commits into mattphillips:main
base: main
Choose a base branch
Loading
from XDGFX:ts-strict
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Convert tests to TypeScript and confirm all passed
  • Loading branch information
XDGFX committed Mar 3, 2024
commit 221d58644f227f6ed86586b23a1aed8dc9052858
4 changes: 4 additions & 0 deletions jest.config.js
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
};
4 changes: 1 addition & 3 deletions src/preserveArray.ts
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ const getLargerArray = (l: unknown[], r: unknown[]) =>
l.length > r.length ? l : r;

const preserve = <T, U>(
diff:
| U
| (DiffAddedType<T, U> & DiffDeletedType<T, U> & DiffUpdatedType<T, U>),
diff: DiffAddedType<T, U> & DiffDeletedType<T, U> & DiffUpdatedType<T, U>,
left: T,
right: U
) => {
Expand Down
33 changes: 27 additions & 6 deletions src/types.ts
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
type ElementType<T> = T extends unknown[]
? T extends (infer U)[]
? U
: never
: T;

type EmptyObject = Record<string, never>;

export type DiffDeletedType<T, U> =
| {
[P in Exclude<keyof T, keyof U>]: undefined;
[P in Exclude<keyof ElementType<T>, keyof ElementType<U>>]: undefined;
}
| Record<string, never>;
| EmptyObject;

export type DiffAddedType<T, U> =
| {
[P in Exclude<keyof U, keyof T>]: U[P];
[P in Exclude<
keyof ElementType<U>,
keyof ElementType<T>
>]: ElementType<U>[P];
}
| Record<string, never>;
| EmptyObject;

// export type DiffUpdatedType<T, U> =
// | {
// [P in keyof T & keyof U]?: DiffUpdatedType<T[P], U[P]>;
// }
// | Record<string, never>;

export type DiffUpdatedType<T, U> =
| {
[P in keyof T & keyof U]?: DiffUpdatedType<T[P], U[P]>;
[P in keyof ElementType<T> & keyof ElementType<U>]?: DiffUpdatedType<
ElementType<T>[P],
ElementType<U>[P]
>;
}
| Record<string, never>;
| U
| EmptyObject;
2 changes: 1 addition & 1 deletion src/updated.ts
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
const updatedDiff = <T, U>(lhs: T, rhs: U): DiffUpdatedType<T, U> => {
if ((lhs as unknown) === (rhs as unknown)) return {};

if (!isObject(lhs) || !isObject(rhs)) return rhs;
if (!isObject(lhs) || !isObject(rhs)) return rhs as DiffUpdatedType<T, U>;

if (isDate(lhs) || isDate(rhs)) {
if (lhs.valueOf() == rhs.valueOf()) return {};
Expand Down
117 changes: 0 additions & 117 deletions test/added.test.js
View file Open in desktop

This file was deleted.

128 changes: 128 additions & 0 deletions test/added.test.ts
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import addedDiff from "../src/added";

describe(".addedDiff", () => {
describe("base case", () => {
describe("equal", () => {
test.each([
["int", 1],
["string", "a"],
["boolean", true],
["null", null],
["undefined", undefined],
["object", { a: 1 }],
["array", [1]],
["function", () => ({})],
["date", new Date()],
])(
"returns empty object when given values of type %s are equal",
(type, value) => {
expect(addedDiff(value, value)).toEqual({});
}
);
});

describe("not equal and not object", () => {
test.each([
[1, 2],
["a", "b"],
[true, false],
["hello", null],
["hello", undefined],
[null, undefined],
[undefined, null],
[null, { a: 1 }],
["872983", { areaCode: "+44", number: "872983" }],
[100, () => ({})],
[() => ({}), 100],
[new Date("2017年01月01日"), new Date("2017年01月02日")],
])(
"returns empty object when values are not equal (%s, %s)",
(lhs, rhs) => {
expect(addedDiff(lhs, rhs)).toEqual({});
}
);
});
});

describe("recursive case", () => {
describe("object", () => {
test("returns empty object when given objects are updated", () => {
expect(addedDiff({ a: 1 }, { a: 2 })).toEqual({});
});

test("returns empty object when right hand side has deletion", () => {
expect(addedDiff({ a: 1, b: 2 }, { a: 1 })).toEqual({});
});

test("returns subset of right hand side value when a key value has been added to the root", () => {
expect(addedDiff({ a: 1 }, { a: 1, b: 2 })).toEqual({ b: 2 });
});

test("returns subset of right hand side value when a key value has been added deeply", () => {
expect(
addedDiff({ a: { b: 1 } }, { a: { b: 1, c: 2 } })
).toEqual({ a: { c: 2 } });
});

test("returns subset of right hand side with added date", () => {
expect(addedDiff({}, { date: new Date("2016") })).toEqual({
date: new Date("2016"),
});
});
});

describe("arrays", () => {
test("returns empty object when array is updated", () => {
expect(addedDiff([1], [2])).toEqual({});
});

test("returns empty object when right hand side array has deletions", () => {
expect(addedDiff([1, 2, 3], [1, 3])).toEqual({});
});

test("returns subset of right hand side array as object of indices to value when right hand side array has additions", () => {
expect(addedDiff([1, 2, 3], [1, 2, 3, 9])).toEqual({ 3: 9 });
});

test("returns subset of right hand side with added date", () => {
expect(addedDiff([], [new Date("2016")])).toEqual({
0: new Date("2016"),
});
});
});

describe("object create null", () => {
test("returns subset of right hand side value when a key value has been added to the root", () => {
const lhs = Object.create(null);
const rhs = Object.create(null);
lhs.a = 1;
rhs.a = 1;
rhs.b = 2;
expect(addedDiff(lhs, rhs)).toEqual({ b: 2 });
});

test("returns subset of right hand side value when a key value has been added deeply", () => {
const lhs = Object.create(null);
const rhs = Object.create(null);
lhs.a = { b: 1 };
rhs.a = { b: 1, c: 2 };
expect(addedDiff(lhs, rhs)).toEqual({ a: { c: 2 } });
});

test("returns subset of right hand side with added date", () => {
const lhs = Object.create(null);
const rhs = Object.create(null);
rhs.date = new Date("2016");
expect(addedDiff(lhs, rhs)).toEqual({ date: new Date("2016") });
});
});

describe("object with non-function hasOwnProperty property", () => {
test("can represent the property in diff despite it being part of Object.prototype", () => {
const lhs = {};
const rhs = { hasOwnProperty: true };
expect(addedDiff(lhs, rhs)).toEqual({ hasOwnProperty: true });
});
});
});
});
File renamed without changes.
Loading

AltStyle によって変換されたページ (->オリジナル) /