Skip to content
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

Audit function parameter and return types (3/2) #461

Merged
merged 10 commits into from
Feb 29, 2024
4 changes: 1 addition & 3 deletions src/distance.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import ColorSpace from "./space.js";
import getColor from "./getColor.js";

/**
* Euclidean distance of colors in an arbitrary color space
*/
export default function distance (color1, color2, space = "lab") {
[color1, color2] = getColor([color1, color2]);

space = ColorSpace.get(space);

// Assume getColor() is called on color in space.from()
let coords1 = space.from(color1);
let coords2 = space.from(color2);

Expand Down
2 changes: 2 additions & 0 deletions src/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ export default function set (color, prop, value) {

return color;
}

set.returns = "color";
2 changes: 2 additions & 0 deletions src/setAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export default function setAll (color, space, coords) {
color.coords = space.to(color.space, coords);
return color;
}

setAll.returns = "color";
7 changes: 5 additions & 2 deletions src/space.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {type, parseCoordGrammar, serializeNumber, mapRange} from "./util.js";
import {getWhite} from "./adapt.js";
import hooks from "./hooks.js";
import getColor from "./getColor.js";

const ε = .000075;

Expand Down Expand Up @@ -173,7 +174,8 @@ export default class ColorSpace {

to (space, coords) {
if (arguments.length === 1) {
[space, coords] = [space.space, space.coords];
const color = getColor(space);
[space, coords] = [color.space, color.coords];
}

space = ColorSpace.get(space);
Expand Down Expand Up @@ -222,7 +224,8 @@ export default class ColorSpace {

from (space, coords) {
if (arguments.length === 1) {
[space, coords] = [space.space, space.coords];
const color = getColor(space);
[space, coords] = [color.space, color.coords];
}

space = ColorSpace.get(space);
Expand Down
65 changes: 39 additions & 26 deletions types/src/color.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ import ColorSpace, { Ref } from "./space.js";
import SpaceAccessors from "./space-coord-accessors.js";

import {
to,
to as toFn,
parse,
serialize,
inGamut,
toGamut,
distance,
equals,
inGamut as inGamutFn,
toGamut as toGamutFn,
distance as distanceFn,
equals as equalsFn,
get,
getAll,
set,
setAll,
getAll as getAllFn,
setAll as setAllFn,
display,
} from "./index-fn.js";

Expand Down Expand Up @@ -69,20 +68,34 @@ export type ToColorPrototype<T extends (...args: any[]) => any> = T extends (
: (...args: A) => R
: never;

/** Convert a function to a Color namespace property (returning a Color) */
export type ToColorNamespace<T extends (...args: any[]) => any> = T extends (
...args: infer A
) => infer R
? T extends { returns: "color" }
? (...args: A) => Color
: (...args: A) => R
: never;

declare namespace Color {
export {
getAll,
set,
setAll,
to,
equals,
inGamut,
toGamut,
distance,
serialize as toString,
};
// Functions defined using Color.defineFunctions
export const getAll: ToColorNamespace<typeof getAllFn>;
export const setAll: ToColorNamespace<typeof setAllFn>;
export const to: ToColorNamespace<typeof toFn>;
export const equals: ToColorNamespace<typeof equalsFn>;
export const inGamut: ToColorNamespace<typeof inGamutFn>;
export const toGamut: ToColorNamespace<typeof toGamutFn>;
export const distance: ToColorNamespace<typeof distanceFn>;
// `get` is defined below as a static method on the Class,
// and `toString` is intentionally not overridden for the namespace

export { util, hooks, WHITES, ColorSpace as Space, parse, defaults };
export const spaces: typeof ColorSpace["registry"];

// Must be manually defined due to overloads
// These should always match the signature of the original function
export function set (color: ColorTypes, prop: Ref, value: number | ((coord: number) => number)): Color;
export function set (color: ColorTypes, props: Record<string, number | ((coord: number) => number)>): Color;
}

declare class Color extends SpaceAccessors implements PlainColorObject {
Expand Down Expand Up @@ -129,13 +142,13 @@ declare class Color extends SpaceAccessors implements PlainColorObject {

// Functions defined using Color.defineFunctions
get: ToColorPrototype<typeof get>;
getAll: ToColorPrototype<typeof getAll>;
setAll: ToColorPrototype<typeof setAll>;
to: ToColorPrototype<typeof to>;
equals: ToColorPrototype<typeof equals>;
inGamut: ToColorPrototype<typeof inGamut>;
toGamut: ToColorPrototype<typeof toGamut>;
distance: ToColorPrototype<typeof distance>;
getAll: ToColorPrototype<typeof getAllFn>;
setAll: ToColorPrototype<typeof setAllFn>;
to: ToColorPrototype<typeof toFn>;
equals: ToColorPrototype<typeof equalsFn>;
inGamut: ToColorPrototype<typeof inGamutFn>;
toGamut: ToColorPrototype<typeof toGamutFn>;
distance: ToColorPrototype<typeof distanceFn>;
toString: ToColorPrototype<typeof serialize>;

// Must be manually defined due to overloads
Expand Down
10 changes: 8 additions & 2 deletions types/src/set.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { ColorTypes, PlainColorObject } from "./color.js";
import { Ref } from "./space.js";

export default function set (
declare namespace set {
let returns: "color";
}

declare function set (
color: ColorTypes,
prop: Ref,
value: number | ((coord: number) => number)
): PlainColorObject;
export default function set (
declare function set (
color: ColorTypes,
props: Record<string, number | ((coord: number) => number)>
): PlainColorObject;

export default set;
2 changes: 1 addition & 1 deletion types/src/setAll.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Color, { ColorTypes, PlainColorObject } from "./color.js";
import { ColorTypes, PlainColorObject } from "./color.js";
import ColorSpace from "./space.js";

declare namespace setAll {
Expand Down
6 changes: 3 additions & 3 deletions types/src/space.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { White } from "./adapt.js";
import Color, { ColorConstructor, ColorObject, Coords, PlainColorObject } from "./color.js";
import { ColorConstructor, Coords, ColorTypes } from "./color.js";

export interface Format {
/** @default "function" */
Expand Down Expand Up @@ -127,7 +127,7 @@ export default class ColorSpace {
white: White;
gamutSpace: ColorSpace;

from (color: {space: ColorSpace, coords: Coords, alpha?: number | undefined}): Coords;
from (color: ColorTypes): Coords;
from (space: string | ColorSpace, coords: Coords): Coords;

getFormat (format?: string | Format): Format | null;
Expand All @@ -136,7 +136,7 @@ export default class ColorSpace {

inGamut (coords: Coords, options?: { epsilon?: number }): boolean;

to (color: {space: ColorSpace, coords: Coords, alpha?: number | undefined}): Coords;
to (color: ColorTypes): Coords;
to (space: string | ColorSpace, coords: Coords): Coords;

toString (): string;
Expand Down
2 changes: 2 additions & 0 deletions types/test/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ set("red", {
});

new Color("red").set("foo", 123); // $ExpectType Color
Color.set("red", "foo", 123); // $ExpectType Color
Color.set(new Color("red"), "foo", 123); // $ExpectType Color
2 changes: 2 additions & 0 deletions types/test/setAll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ setAll(

new Color("red").setAll("srgb", [1, 2, 3]); // $ExpectType Color
new Color("red").setAll(sRGB, [1, 2, 3]); // $ExpectType Color
Color.setAll("red", "srgb", [1, 2, 3]); // $ExpectType Color
Color.setAll(new Color("red"), "srgb", [1, 2, 3]); // $ExpectType Color
3 changes: 2 additions & 1 deletion types/test/spaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@ ColorSpace.resolveCoord("p3.0", "p3");
ColorSpace.resolveCoord(["p3", "r"], "p3");

space.to(new Color("red")); // $ExpectType Coords
space.to("red"); // $ExpectType Coords
space.to({space: space, coords: [1, 2, 3], alpha: 1}); // $ExpectType Coords
space.to({space: space, coords: [1, 2, 3]}); // $ExpectType Coords
space.to(space, [1, 2, 3]); // $ExpectType Coords
space.to("srgb", [1, 2, 3]); // $ExpectType Coords

space.from(new Color("red")); // $ExpectType Coords
space.from("red"); // $ExpectType Coords
space.from({space: space, coords: [1, 2, 3], alpha: 1}); // $ExpectType Coords
space.from({space: space, coords: [1, 2, 3]}); // $ExpectType Coords
space.from(space, [1, 2, 3]); // $ExpectType Coords
space.from("srgb", [1, 2, 3]); // $ExpectType Coords

5 changes: 5 additions & 0 deletions types/test/to.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Color from "colorjs.io/src";
import to from "colorjs.io/src/to";

// @ts-expect-error
Expand All @@ -8,3 +9,7 @@ to("red");

to("red", "srgb"); // $ExpectType PlainColorObject
to("red", "srgb", { inGamut: false }); // $ExpectType PlainColorObject

new Color("red").to("srgb"); // $ExpectType Color
Color.to("red", "srgb"); // $ExpectType Color
Color.to(new Color("red"), "srgb"); // $ExpectType Color
2 changes: 2 additions & 0 deletions types/test/toGamut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ new Color("red").toGamut(); // $ExpectType Color
new Color("red").toGamut({ method: "clip", space: "srgb" }); // $ExpectType Color
new Color("red").toGamut({ method: "clip", space: sRGB }); // $ExpectType Color
new Color("red").toGamut("srgb"); // $ExpectType Color
Color.toGamut("red"); // $ExpectType Color
Color.toGamut(new Color("red")); // $ExpectType Color