[classnames] improve types for classnames/bind and add types for classnames/dedupe (#36458)

* enable classnames/bind usage without bind

* add test for classnames/bind

* add classnames/dedupe support

* same default export trick for classnames/bind

* add me to definition author

* add dedupe.d.ts to files
This commit is contained in:
uhyo 2019-07-03 01:41:39 +09:00 committed by Ryan Cavanaugh
parent dd3c25ab8e
commit cf258953db
6 changed files with 39 additions and 15 deletions

View File

@ -1,3 +1,11 @@
import classNames = require('./index');
import { ClassNamesFn } from './types';
export function bind(styles: Record<string, string>): typeof classNames;
interface ClassNamesBind extends ClassNamesFn {
bind(styles: Record<string, string>): ClassNamesFn;
}
type ClassNamesBindExport = ClassNamesBind & {
default: ClassNamesBind;
};
declare const classNamesBind: ClassNamesBindExport;
export = classNamesBind;

View File

@ -1,6 +1,8 @@
import classNames = require('classnames');
import * as classNames2 from 'classnames';
import * as cn from 'classnames/bind';
import classNamesDedupe = require('classnames/dedupe');
import * as classNamesDedupe2 from 'classnames/dedupe';
classNames2('foo', 'bar'); // => 'foo bar'
@ -17,7 +19,7 @@ classNames(['foo', 'bar', 'baz']); // => 'foo bar baz'
classNames([1, 2, 3]); // => '1 2 3'
classNames([{ foo: true, bar: false }, { baz: true }]); // => 'foo baz'
classNames(["foo", ["bar", {baz: true}]]); // => 'foo bar baz'
classNames(['foo', ['bar', { baz: true }]]); // => 'foo bar baz'
// falsey values are just ignored
classNames(null, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
@ -28,9 +30,9 @@ classNames(null, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
// Support for CSS-Modules. Example from README:
// https://github.com/JedWatson/classnames/blob/master/README.md#alternate-bind-version-for-css-modules
const styles = {
foo: 'abc',
bar: 'def',
baz: 'xyz'
foo: 'abc',
bar: 'def',
baz: 'xyz',
};
const cx = cn.bind(styles);
@ -40,4 +42,11 @@ const className = cx('foo', ['bar'], { baz: true }); // => "abc def xyz"
cx(null, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
// true is just ignored
cx(true || "foo");
cx(true || 'foo');
// export of classnames/bind can be used the same as normal classnames
cn(null, 'bar', undefined, 1, ['foo', 'bar', { baz: true }], '');
// classnames/dedupe has same usage as normal classnames
classNamesDedupe('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'
classNamesDedupe2('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'

5
types/classnames/dedupe.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { ClassNamesExport } from './types';
declare const classNamesDedupe: ClassNamesExport;
export = classNamesDedupe;

View File

@ -7,14 +7,11 @@
// Michal Adamczyk <https://github.com/mradamczyk>
// Marvin Hagemeister <https://github.com/marvinhagemeister>
// Josh McCullough <https://github.com/joshmccullough>
// uhyo <https://github.com/uhyo>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
import { ClassValue } from './types';
type ClassNamesFn = (...classes: ClassValue[]) => string;
type ClassNamesExport = ClassNamesFn & { default: ClassNamesFn };
import { ClassValue, ClassNamesExport } from './types';
declare const classNames: ClassNamesExport;

View File

@ -19,7 +19,8 @@
"files": [
"index.d.ts",
"bind.d.ts",
"dedupe.d.ts",
"types.d.ts",
"classnames-tests.ts"
]
}
}

View File

@ -1,9 +1,13 @@
// This is the only way I found to break circular references between ClassArray and ClassValue
// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
export interface ClassArray extends Array<ClassValue> { } // tslint:disable-line no-empty-interface
export interface ClassArray extends Array<ClassValue> {} // tslint:disable-line no-empty-interface
export interface ClassDictionary {
[id: string]: any;
[id: string]: any;
}
export type ClassValue = string | number | ClassDictionary | ClassArray | undefined | null | boolean;
export type ClassNamesFn = (...classes: ClassValue[]) => string;
export type ClassNamesExport = ClassNamesFn & { default: ClassNamesFn };