Skip to content

Commit

Permalink
feat: Remove IsEmptyInterface (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Jan 21, 2020
1 parent e1ae432 commit 8ef85cd
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 105 deletions.
20 changes: 10 additions & 10 deletions __snapshots__/IsEmptyInterface
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
sources/IsEmptyInterface.test.ts(11,27): error TS2554: Expected 1 arguments, but got 0.
Files: 54
Lines: 61523
Nodes: 180439
Identifiers: 62593
Symbols: 104001
Types: 36907
Memory used: 133717K
Lines: 61475
Nodes: 180254
Identifiers: 62545
Symbols: 102462
Types: 33716
Memory used: 146633K
I/O read: 0.02s
I/O write: 0.00s
Parse time: 0.68s
Bind time: 0.76s
Check time: 3.13s
Parse time: 0.65s
Bind time: 0.28s
Check time: 3.33s
Emit time: 0.00s
Total time: 4.57s
Total time: 4.26s
6 changes: 3 additions & 3 deletions vendor/@material-ui/core/styles/createMixins.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Breakpoints } from './createBreakpoints';
import { Spacing } from './createSpacing';
import { CSSProperties } from './withStyles';
import * as React from 'react';

export interface Mixins {
gutters: (styles?: CSSProperties) => CSSProperties;
toolbar: CSSProperties;
gutters: (styles?: React.CSSProperties) => React.CSSProperties;
toolbar: React.CSSProperties;
// ... use interface declaration merging to add custom mixins
}

Expand Down
33 changes: 15 additions & 18 deletions vendor/@material-ui/core/styles/createTypography.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Palette } from './createPalette';
import * as React from 'react';
import { CSSProperties } from './withStyles';

export type ThemeStyle =
export type Variant =
| 'h1'
| 'h2'
| 'h3'
Expand All @@ -18,37 +19,33 @@ export type ThemeStyle =

export interface FontStyle
extends Required<{
fontFamily: CSSProperties['fontFamily'];
fontFamily: React.CSSProperties['fontFamily'];
fontSize: number;
fontWeightLight: CSSProperties['fontWeight'];
fontWeightRegular: CSSProperties['fontWeight'];
fontWeightMedium: CSSProperties['fontWeight'];
fontWeightBold: CSSProperties['fontWeight'];
fontWeightLight: React.CSSProperties['fontWeight'];
fontWeightRegular: React.CSSProperties['fontWeight'];
fontWeightMedium: React.CSSProperties['fontWeight'];
fontWeightBold: React.CSSProperties['fontWeight'];
}> {}

export interface FontStyleOptions extends Partial<FontStyle> {
htmlFontSize?: number;
allVariants?: CSSProperties;
allVariants?: React.CSSProperties;
}

export type TypographyStyle = Required<
Pick<CSSProperties, 'fontFamily' | 'fontSize' | 'fontWeight' | 'fontStyle' | 'color'>
> &
Partial<Pick<CSSProperties, 'letterSpacing' | 'lineHeight' | 'textTransform'>>;

export interface TypographyStyleOptions extends Partial<TypographyStyle> {}
// TODO: which one should actually be allowed to be subject to module augmentation?
// current type vs interface decision is kept for historical reasons until we
// made a decision
export type TypographyStyle = CSSProperties;
export interface TypographyStyleOptions extends TypographyStyle {}

export interface TypographyUtils {
pxToRem: (px: number) => string;
}

export interface Typography
extends Record<ThemeStyle, TypographyStyle>,
FontStyle,
TypographyUtils {}
export interface Typography extends Record<Variant, TypographyStyle>, FontStyle, TypographyUtils {}

export interface TypographyOptions
extends Partial<Record<ThemeStyle, TypographyStyleOptions> & FontStyleOptions> {}
extends Partial<Record<Variant, TypographyStyleOptions> & FontStyleOptions> {}

export default function createTypography(
palette: Palette,
Expand Down
16 changes: 13 additions & 3 deletions vendor/@material-ui/core/styles/makeStyles.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { Theme as DefaultTheme } from './createMuiTheme';
import { Styles, WithStylesOptions } from '@material-ui/styles/withStyles';
import { StylesHook } from '@material-ui/styles/makeStyles';
import { ClassNameMap, Styles, WithStylesOptions } from '@material-ui/styles/withStyles';

import { Omit } from '@material-ui/types';

/**
* `makeStyles` where the passed `styles` do not depend on props
*/
export default function makeStyles<Theme = DefaultTheme, ClassKey extends string = string>(
style: Styles<Theme, {}, ClassKey>,
options?: Omit<WithStylesOptions<Theme>, 'withTheme'>,
): (props?: any) => ClassNameMap<ClassKey>;
/**
* `makeStyles` where the passed `styles` do depend on props
*/
export default function makeStyles<
Theme = DefaultTheme,
Props extends {} = {},
ClassKey extends string = string
>(
styles: Styles<Theme, Props, ClassKey>,
options?: Omit<WithStylesOptions<Theme>, 'withTheme'>,
): StylesHook<Styles<Theme, Props, ClassKey>>;
): (props: Props) => ClassNameMap<ClassKey>;
36 changes: 8 additions & 28 deletions vendor/@material-ui/styles/makeStyles/makeStyles.d.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,27 @@
import {
ClassKeyOfStyles,
ClassNameMap,
PropsOfStyles,
Styles,
WithStylesOptions,
} from '@material-ui/styles/withStyles';
import { Omit, IsAny, Or, IsEmptyInterface } from '@material-ui/types';
import { Omit } from '@material-ui/types';
import { DefaultTheme } from '../defaultTheme';

/**
* @internal
*
* If a style callback is given with `theme => stylesOfTheme` then typescript
* infers `Props` to `any`.
* If a static object is given with { ...members } then typescript infers `Props`
* to `{}`.
*
* So we require no props in `useStyles` if `Props` in `makeStyles(styles)` is
* inferred to either `any` or `{}`
* `makeStyles` where the passed `styles` do not depend on props
*/
export type StylesRequireProps<S> = Or<
IsAny<PropsOfStyles<S>>,
IsEmptyInterface<PropsOfStyles<S>>
> extends true
? false
: true;

export default function makeStyles<Theme = DefaultTheme, ClassKey extends string = string>(
style: Styles<Theme, {}, ClassKey>,
options?: Omit<WithStylesOptions<Theme>, 'withTheme'>,
): (props?: any) => ClassNameMap<ClassKey>;
/**
* @internal
*
* `Props` are `any` either by explicit annotation or if there are no callbacks
* from which the typechecker could infer a type so it falls back to `any`.
* See the test cases for examples and implications of explicit `any` annotation
* `makeStyles` where the passed `styles` do depend on props
*/
export type StylesHook<S extends Styles<any, any>> = StylesRequireProps<S> extends false
? (props?: any) => ClassNameMap<ClassKeyOfStyles<S>>
: (props: PropsOfStyles<S>) => ClassNameMap<ClassKeyOfStyles<S>>;

export default function makeStyles<
Theme = DefaultTheme,
Props extends {} = {},
ClassKey extends string = string
>(
styles: Styles<Theme, Props, ClassKey>,
options?: Omit<WithStylesOptions<Theme>, 'withTheme'>,
): StylesHook<Styles<Theme, Props, ClassKey>>;
): (props: Props) => ClassNameMap<ClassKey>;
20 changes: 15 additions & 5 deletions vendor/@material-ui/styles/withStyles/withStyles.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { PropInjector, IsEmptyInterface } from '@material-ui/types';
import { PropInjector } from '@material-ui/types';
import * as CSS from 'csstype';
import * as JSS from 'jss';
import { DefaultTheme } from '../defaultTheme';
Expand All @@ -18,7 +18,14 @@ export interface BaseCSSProperties extends CSS.Properties<number | string> {

export interface CSSProperties extends BaseCSSProperties {
// Allow pseudo selectors and media queries
[k: string]: BaseCSSProperties[keyof BaseCSSProperties] | CSSProperties;
// `unknown` is used since TS does not allow assigning an interface without
// an index signature to one with an index signature. This is to allow type safe
// module augmentation.
// Technically we want any key not typed in `BaseCSSProperties` to be of type
// `CSSProperties` but this doesn't work. The index signature needs to cover
// BaseCSSProperties as well. Usually you would use `BaseCSSProperties[keyof BaseCSSProperties]`
// but this would not allow assigning React.CSSProperties to CSSProperties
[k: string]: unknown | CSSProperties;
}

export type BaseCreateCSSProperties<Props extends object = {}> = {
Expand All @@ -43,9 +50,12 @@ export interface CreateCSSProperties<Props extends object = {}>
*/
export type StyleRules<Props extends object = {}, ClassKey extends string = string> = Record<
ClassKey,
IsEmptyInterface<Props> extends true
? CSSProperties | (() => CSSProperties)
: CreateCSSProperties<Props> | ((props: Props) => CreateCSSProperties<Props>)
// JSS property bag
| CSSProperties
// JSS property bag where values are based on props
| CreateCSSProperties<Props>
// JSS property bag based on props
| ((props: Props) => CreateCSSProperties<Props>)
>;

/**
Expand Down
38 changes: 0 additions & 38 deletions vendor/@material-ui/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,41 +44,3 @@ export type Omit<T, K extends keyof any> = T extends any ? Pick<T, Exclude<keyof
* @internal
*/
export type Overwrite<T, U> = Omit<T, keyof U> & U;

/**
* Returns true if T is any, otherwise false
*/
// https://stackoverflow.com/a/49928360/3406963 without generic branch types
export type IsAny<T> = 0 extends (1 & T) ? true : false;

export type Or<A, B, C = false> = A extends true
? true
: B extends true
? true
: C extends true
? true
: false;

export type And<A, B, C = true> = A extends true
? B extends true
? C extends true
? true
: false
: false
: false;

/**
* @internal
*
* check if a type is `{}`
*
* 1. false if the given type has any members
* 2. false if the type is `object` which is the only other type with no members
* {} is a top type so e.g. `string extends {}` but not `string extends object`
* 3. false if the given type is `unknown`
*/
export type IsEmptyInterface<T> = And<
keyof T extends never ? true : false,
string extends T ? true : false,
unknown extends T ? false : true
>;

0 comments on commit 8ef85cd

Please sign in to comment.