From 6d6bea5b12438054d835cc7ea39384defdc026b0 Mon Sep 17 00:00:00 2001 From: keenondrums Date: Sun, 24 Jun 2018 17:37:50 -0600 Subject: [PATCH 1/2] Feature Added: redux-orm typings --- types/redux-orm/index.d.ts | 217 +++++++++++++++++++++++++++++ types/redux-orm/redux-orm-tests.ts | 79 +++++++++++ types/redux-orm/tsconfig.json | 22 +++ types/redux-orm/tslint.json | 1 + 4 files changed, 319 insertions(+) create mode 100644 types/redux-orm/index.d.ts create mode 100644 types/redux-orm/redux-orm-tests.ts create mode 100644 types/redux-orm/tsconfig.json create mode 100644 types/redux-orm/tslint.json diff --git a/types/redux-orm/index.d.ts b/types/redux-orm/index.d.ts new file mode 100644 index 0000000000..1f116aa255 --- /dev/null +++ b/types/redux-orm/index.d.ts @@ -0,0 +1,217 @@ +// Type definitions for redux-orm 0.9.4 +// Project: https://github.com/tommikaikkonen/redux-orm#readme +// Definitions by: Andrey Goncharov +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +interface IORMId { + id: string +} + +interface ITableState { + items: string[], + itemsById: { [index: string]: Item }, + meta: Meta +} + +interface IORMCommonState { + [index: string]: ITableState +} + +type ISession = Session & { [P in keyof State]: typeof Model } + +type IModel = Model & Fields & VirtualFields & Additional & IORMId + +// TODO: Refine me +type IModelProps = any + +// TODO: Refine me +interface IDB { + getEmptyState: any, + query: any, + update: any, + describe: any +} + +// TODO: Refine me +interface ISchemaSpec { + tables: any +} + +// TODO: Refine me +interface IORMOpts { + createDatabase: (schemaSpec: ISchemaSpec) => any +} + +interface IModelFields { + [index: string]: Attribute | ForeignKey | ManyToMany | OneToOne +} + +interface IModelVirtualFields { + [index: string]: any +} + +export class ORM { + constructor(opts?: IORMOpts) + register(...model: Array): void + register(...model: Array): void + registerManyToManyModelsFor(model: typeof Model): void + get(modelName: string): typeof Model + getModelClasses(): Array + isFieldInstalled(modelName: string, fieldName: string): boolean + setFieldInstalled(modelName: string, fieldName: string): void + generateSchemaSpec(): ISchemaSpec + getDatabase(): IDB + getEmptyState(): State + session(state: State): ISession + mutableSession(state: State): ISession + + private _attachQuerySetMethods(model: typeof Model): void + private _setupModelPrototypes(models: Array): void +} + +export class Model { + static readonly idAttribute: string + static readonly session: ISession + static readonly _sessionData: any // TODO + static readonly query: QuerySet + + static modelName: string + static fields: IModelFields + static virtualFields: IModelVirtualFields + static querySetClass: typeof QuerySet + + static toString(): string + static options(): T + static _getTableOpts(): T + static markAccessed(): void + static connect(session: Session): void + static getQuerySet = QuerySet>(): T + static invalidateClassCache(): void + static all(): QuerySet + static create(props: Fields): IModel + static upsert(props: Partial): IModel + static withId(id: string): IModel + static hasId(id: string): boolean + static _findDatabaseRows(lookupObj: object): any // TODO + static get(lookupObj: Object): IModel + static reducer(session: ISession, action: any): any + + readonly ref: Fields & Additional & IORMId + + constructor(props: IModelProps) + + getClass(): string + getId(): string + toString(): string + equals(otherModel: IModel): boolean + set(propertyName: string, value: T): void + update(userMergeObj: Partial): void + refreshFromState(): void + delete(): void + + private _onDelete(): void + private _initFields(props: IModelProps): void + private _refreshMany2Many(relations: any): void //TODO +} + +type IQuerySetClauses = any // TODO +type IQuerySetOpts = any // TODO +declare class QuerySet { + static addSharedMethod(methodName: string): void + + constructor(modelClass: typeof Model, clauses: IQuerySetClauses, opts: IQuerySetOpts) + + toString(): string + toRefArray(): Array + toModelArray(): Array> + count(): number + exists(): boolean + at(index: string): IModel | undefined + first(): IModel | undefined + last(): IModel | undefined + all(): QuerySet + filter(lookupObj: object): QuerySet // TODO + exclude(lookupObj: object): QuerySet // TODO + orderBy(iteratees: any, orders: any): QuerySet // TODO + update(mergeObj: Partial): void + delete(): void + + private _evaluate(): void + private _new(clauses: IQuerySetClauses, userOpts: IQuerySetOpts): QuerySet +} + +export class Session { + readonly accessedModels: string[] + schema: ORM + db: IDB + initialState: State + withMutations: boolean + batchToken: any + sessionBoundModels: Array + models: Array + state: State + + constructor(schema: ORM, db: IDB, state: State, withMutations: boolean, batchToken: any) // TODO + + markAccessed(modelName: string): void + getDataForModel(modelName: string): object + applyUpdate(updateSpec: any): any // TODO + query(querySpec: any): any // TODO +} + +interface IAttributeOpts { + getDefault?: () => any +} + +export class Attribute { + constructor (opts: IAttributeOpts) + install(model: typeof Model, fieldName: string, orm: ORM): void +} + +interface IRelationalFieldOpts { + to: string, + relatedName?: string, + through?: string, + throughFields?: { + to: string, + from: string + } +} + +export class RelationalField { + constructor (toModelName: string, relatedName?: string) + constructor (opts: IRelationalFieldOpts) + getClass: typeof RelationalField +} + +export class ForeignKey extends RelationalField { + install(model: typeof Model, fieldName: string, orm: ORM): void +} + +export class ManyToMany extends RelationalField { + install(model: typeof Model, fieldName: string, orm: ORM): void +} + +export class OneToOne extends RelationalField { + install(model: typeof Model, fieldName: string, orm: ORM): void +} + +export function attr(opts?: IAttributeOpts): Attribute + +export function fk(toModelName: string, relatedName?: string): ForeignKey +export function fk(opts: IRelationalFieldOpts): ForeignKey + + +export function many(toModelName: string, relatedName?: string): ManyToMany +export function many(opts: IRelationalFieldOpts): ManyToMany + +export function oneToOne(toModelName: string, relatedName?: string): OneToOne +export function oneToOne(opts: IRelationalFieldOpts): OneToOne + +type IUpdater = (session: ISession, action: any) => any + +export function createReducer(orm: ORM, updater?: IUpdater): (state: State, action: any) => State + +type IORMSelector = (session: ISession, ...args: any[]) => Result + +export function createSelector(orm: ORM, ...args: IORMSelector[]): (state: State) => Result diff --git a/types/redux-orm/redux-orm-tests.ts b/types/redux-orm/redux-orm-tests.ts new file mode 100644 index 0000000000..4e597b91b0 --- /dev/null +++ b/types/redux-orm/redux-orm-tests.ts @@ -0,0 +1,79 @@ +import { attr, createSelector as createSelectorORM, IORMCommonState, IORMId, ITableState, ISession, Model, ORM } from 'redux-orm'; + +// Model +export class Test extends Model { + static modelName = 'Test'; + + static fields = { + test: attr(), + isFetching: attr({ getDefault: () => false }), + id: attr() + }; +} + +// core data which we do not have defaults for +export interface TestStateItem { + test: string; +} + +// optional data we provide defaults for +export interface FetchIndicatorState { + isFetching: boolean; +} + +// id attr is added automatically by redux-orm therefore we have IORMId interface +export type TestState = ITableState; + +export interface TestORMState extends IORMCommonState { + Test: TestState; +} + +interface TestORMModels { + Test: typeof Test; +} + +const orm = new ORM(); +orm.register(Test); + +// Reducer +interface TestDTO { + test: string; +} + +interface Action

{ + type: string; + payload: P; +} + +const reducerAddItem = (state: TestORMState, action: Action): TestORMState => { + const session = orm.session(state); + session.Test.upsert(action.payload); + return session.state; +}; + +// Selector +interface TestDisplayItem { + test: string; +} +type TestDisplayItemList = TestDisplayItem[]; + +// Just for the example below. Use real createSelector from reselect in your app +const createSelector = (param1Creator: (state: S) => P1, combiner: (param1: P1) => R): (state: S) => R => (state) => + combiner(param1Creator(state)); + +interface RootState { + test: TestORMState; +} + +export const makeGetTestDisplayList = () => { + const ormSelector = createSelectorORM(orm, (session: ISession) => + session.Test + .all() + .toRefArray() + .map((item) => ({ ...item })) + ); + return createSelector( + ({ test }) => test, + ormSelector + ); +}; diff --git a/types/redux-orm/tsconfig.json b/types/redux-orm/tsconfig.json new file mode 100644 index 0000000000..d0db87216d --- /dev/null +++ b/types/redux-orm/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "redux-orm-tests.ts" + ] +} diff --git a/types/redux-orm/tslint.json b/types/redux-orm/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/redux-orm/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } From 2ca6a7806bfad69732c9f57b29f02ad369103e39 Mon Sep 17 00:00:00 2001 From: keenondrums Date: Sun, 24 Jun 2018 18:14:06 -0600 Subject: [PATCH 2/2] Fix linting errors --- types/redux-orm/index.d.ts | 286 ++++++++++++++--------------- types/redux-orm/redux-orm-tests.ts | 11 +- types/redux-orm/tsconfig.json | 1 + 3 files changed, 148 insertions(+), 150 deletions(-) diff --git a/types/redux-orm/index.d.ts b/types/redux-orm/index.d.ts index 1f116aa255..31fffa1273 100644 --- a/types/redux-orm/index.d.ts +++ b/types/redux-orm/index.d.ts @@ -1,217 +1,215 @@ -// Type definitions for redux-orm 0.9.4 +// Type definitions for redux-orm 0.9 // Project: https://github.com/tommikaikkonen/redux-orm#readme // Definitions by: Andrey Goncharov // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 -interface IORMId { - id: string +export interface ORMId { + id: string; } -interface ITableState { - items: string[], - itemsById: { [index: string]: Item }, - meta: Meta +export interface TableState { + items: string[]; + itemsById: { [index: string]: Item }; + meta: Meta; } -interface IORMCommonState { - [index: string]: ITableState +export interface ORMCommonState { + [index: string]: TableState; } -type ISession = Session & { [P in keyof State]: typeof Model } +export type SessionWithModels = Session & { [P in keyof State]: typeof Model }; -type IModel = Model & Fields & VirtualFields & Additional & IORMId +export type ModelWithFields = Model & Fields & VirtualFields & Additional & ORMId; // TODO: Refine me -type IModelProps = any +export type ModelProps = any; // TODO: Refine me -interface IDB { - getEmptyState: any, - query: any, - update: any, - describe: any +export interface DB { + getEmptyState: any; + query: any; + update: any; + describe: any; } // TODO: Refine me -interface ISchemaSpec { - tables: any +export interface SchemaSpec { + tables: any; } // TODO: Refine me -interface IORMOpts { - createDatabase: (schemaSpec: ISchemaSpec) => any +export interface ORMOpts { + createDatabase: (schemaSpec: SchemaSpec) => any; } -interface IModelFields { - [index: string]: Attribute | ForeignKey | ManyToMany | OneToOne +export interface ModelFields { + [index: string]: Attribute | ForeignKey | ManyToMany | OneToOne; } -interface IModelVirtualFields { - [index: string]: any +export interface ModelVirtualFields { + [index: string]: any; } -export class ORM { - constructor(opts?: IORMOpts) - register(...model: Array): void - register(...model: Array): void - registerManyToManyModelsFor(model: typeof Model): void - get(modelName: string): typeof Model - getModelClasses(): Array - isFieldInstalled(modelName: string, fieldName: string): boolean - setFieldInstalled(modelName: string, fieldName: string): void - generateSchemaSpec(): ISchemaSpec - getDatabase(): IDB - getEmptyState(): State - session(state: State): ISession - mutableSession(state: State): ISession +export class ORM { + constructor(opts?: ORMOpts) + register(...model: Array): void; + register(...model: Array): void; + registerManyToManyModelsFor(model: typeof Model): void; + get(modelName: string): typeof Model; + getModelClasses(): Array; + isFieldInstalled(modelName: string, fieldName: string): boolean; + setFieldInstalled(modelName: string, fieldName: string): void; + generateSchemaSpec(): SchemaSpec; + getDatabase(): DB; + getEmptyState(): State; + session(state: State): SessionWithModels; + mutableSession(state: State): SessionWithModels; - private _attachQuerySetMethods(model: typeof Model): void - private _setupModelPrototypes(models: Array): void + private _attachQuerySetMethods(model: typeof Model): void; + private _setupModelPrototypes(models: Array): void; } export class Model { - static readonly idAttribute: string - static readonly session: ISession - static readonly _sessionData: any // TODO - static readonly query: QuerySet + static readonly idAttribute: string; + static readonly session: SessionWithModels; + static readonly _sessionData: any; // TODO + static readonly query: QuerySet; - static modelName: string - static fields: IModelFields - static virtualFields: IModelVirtualFields - static querySetClass: typeof QuerySet + static modelName: string; + static fields: ModelFields; + static virtualFields: ModelVirtualFields; + static querySetClass: typeof QuerySet; - static toString(): string - static options(): T - static _getTableOpts(): T - static markAccessed(): void - static connect(session: Session): void - static getQuerySet = QuerySet>(): T - static invalidateClassCache(): void - static all(): QuerySet - static create(props: Fields): IModel - static upsert(props: Partial): IModel - static withId(id: string): IModel - static hasId(id: string): boolean - static _findDatabaseRows(lookupObj: object): any // TODO - static get(lookupObj: Object): IModel - static reducer(session: ISession, action: any): any + static toString(): string; + static options(): object; + static _getTableOpts(): object; + static markAccessed(): void; + static connec(session: Session): void; + static getQuerySet(): QuerySet; + static invalidateClassCache(): void; + static all(): QuerySet; + static create(props: Fields): ModelWithFields; + static upsert(props: Partial): ModelWithFields; + static withId(id: string): ModelWithFields; + static hasId(id: string): boolean; + static _findDatabaseRows(lookupObj: object): any; // TODO + static get(lookupObj: object): ModelWithFields; + static reducer(session: SessionWithModels, action: any): any; - readonly ref: Fields & Additional & IORMId + readonly ref: Fields & Additional & ORMId; - constructor(props: IModelProps) + constructor(props: ModelProps) - getClass(): string - getId(): string - toString(): string - equals(otherModel: IModel): boolean - set(propertyName: string, value: T): void - update(userMergeObj: Partial): void - refreshFromState(): void - delete(): void + getClass(): string; + getId(): string; + toString(): string; + equals(otherModel: ModelWithFields): boolean; + set(propertyName: string, value: any): void; + update(userMergeObj: Partial): void; + refreshFromState(): void; + delete(): void; - private _onDelete(): void - private _initFields(props: IModelProps): void - private _refreshMany2Many(relations: any): void //TODO + private _onDelete(): void; + private _initFields(props: ModelProps): void; + private _refreshMany2Many(relations: any): void; // TODO } -type IQuerySetClauses = any // TODO -type IQuerySetOpts = any // TODO -declare class QuerySet { - static addSharedMethod(methodName: string): void +export type QuerySetClauses = any; // TODO +export type QuerySetOpts = any; // TODO +export class QuerySet { + static addSharedMethod(methodName: string): void; - constructor(modelClass: typeof Model, clauses: IQuerySetClauses, opts: IQuerySetOpts) + constructor(modelClass: typeof Model, clauses: QuerySetClauses, opts: QuerySetOpts) - toString(): string - toRefArray(): Array - toModelArray(): Array> - count(): number - exists(): boolean - at(index: string): IModel | undefined - first(): IModel | undefined - last(): IModel | undefined - all(): QuerySet - filter(lookupObj: object): QuerySet // TODO - exclude(lookupObj: object): QuerySet // TODO - orderBy(iteratees: any, orders: any): QuerySet // TODO - update(mergeObj: Partial): void - delete(): void + toString(): string; + toRefArray(): Array; + toModelArray(): Array>; + count(): number; + exists(): boolean; + at(index: string): ModelWithFields | undefined; + first(): ModelWithFields | undefined; + last(): ModelWithFields | undefined; + all(): QuerySet; + filter(lookupObj: object): QuerySet; // TODO + exclude(lookupObj: object): QuerySet; // TODO + orderBy(iteratees: any, orders: any): QuerySet; // TODO + update(mergeObj: Partial): void; + delete(): void; - private _evaluate(): void - private _new(clauses: IQuerySetClauses, userOpts: IQuerySetOpts): QuerySet + private _evaluate(): void; + private _new(clauses: QuerySetClauses, userOpts: QuerySetOpts): QuerySet; } -export class Session { - readonly accessedModels: string[] - schema: ORM - db: IDB - initialState: State - withMutations: boolean - batchToken: any - sessionBoundModels: Array - models: Array - state: State +export class Session { + readonly accessedModels: string[]; + schema: ORM; + db: DB; + initialState: State; + withMutations: boolean; + batchToken: any; + sessionBoundModels: Array; + models: Array; + state: State; - constructor(schema: ORM, db: IDB, state: State, withMutations: boolean, batchToken: any) // TODO - - markAccessed(modelName: string): void - getDataForModel(modelName: string): object - applyUpdate(updateSpec: any): any // TODO - query(querySpec: any): any // TODO + constructor(schema: ORM, db: DB, state: State, withMutations: boolean, batchToken: any) // TODO + + markAccessed(modelName: string): void; + getDataForModel(modelName: string): object; + applyUpdate(updateSpec: any): any; // TODO + query(querySpec: any): any; // TODO } -interface IAttributeOpts { - getDefault?: () => any +export interface AttributeOpts { + getDefault?: () => any; } export class Attribute { - constructor (opts: IAttributeOpts) - install(model: typeof Model, fieldName: string, orm: ORM): void + constructor(opts: AttributeOpts) + install(model: typeof Model, fieldName: string, orm: ORM): void; } -interface IRelationalFieldOpts { - to: string, - relatedName?: string, - through?: string, +export interface RelationalFieldOpts { + to: string; + relatedName?: string; + through?: string; throughFields?: { - to: string, - from: string - } + to: string; + from: string; + }; } export class RelationalField { - constructor (toModelName: string, relatedName?: string) - constructor (opts: IRelationalFieldOpts) - getClass: typeof RelationalField + constructor(toModelName: string, relatedName?: string) + constructor(opts: RelationalFieldOpts) + getClass: typeof RelationalField; } export class ForeignKey extends RelationalField { - install(model: typeof Model, fieldName: string, orm: ORM): void + install(model: typeof Model, fieldName: string, orm: ORM): void; } export class ManyToMany extends RelationalField { - install(model: typeof Model, fieldName: string, orm: ORM): void + install(model: typeof Model, fieldName: string, orm: ORM): void; } export class OneToOne extends RelationalField { - install(model: typeof Model, fieldName: string, orm: ORM): void + install(model: typeof Model, fieldName: string, orm: ORM): void; } -export function attr(opts?: IAttributeOpts): Attribute +export function attr(opts?: AttributeOpts): Attribute; -export function fk(toModelName: string, relatedName?: string): ForeignKey -export function fk(opts: IRelationalFieldOpts): ForeignKey +export function fk(toModelName: string, relatedName?: string): ForeignKey; +export function fk(opts: RelationalFieldOpts): ForeignKey; +export function many(toModelName: string, relatedName?: string): ManyToMany; +export function oneToOne(toModelName: string, relatedName?: string): OneToOne; +export function oneToOne(opts: RelationalFieldOpts): OneToOne; -export function many(toModelName: string, relatedName?: string): ManyToMany -export function many(opts: IRelationalFieldOpts): ManyToMany +export type Updater = (session: SessionWithModels, action: any) => any; -export function oneToOne(toModelName: string, relatedName?: string): OneToOne -export function oneToOne(opts: IRelationalFieldOpts): OneToOne +export function createReducer(orm: ORM, updater?: Updater): (state: State, action: any) => State; -type IUpdater = (session: ISession, action: any) => any +export type ORMSelector = (session: SessionWithModels, ...args: any[]) => Result; -export function createReducer(orm: ORM, updater?: IUpdater): (state: State, action: any) => State - -type IORMSelector = (session: ISession, ...args: any[]) => Result - -export function createSelector(orm: ORM, ...args: IORMSelector[]): (state: State) => Result +export function createSelector(orm: ORM, ...args: Array>): (state: State) => any; diff --git a/types/redux-orm/redux-orm-tests.ts b/types/redux-orm/redux-orm-tests.ts index 4e597b91b0..045f4a3554 100644 --- a/types/redux-orm/redux-orm-tests.ts +++ b/types/redux-orm/redux-orm-tests.ts @@ -1,4 +1,4 @@ -import { attr, createSelector as createSelectorORM, IORMCommonState, IORMId, ITableState, ISession, Model, ORM } from 'redux-orm'; +import { attr, createSelector as createSelectorORM, ORMCommonState, ORMId, QuerySet, TableState, SessionWithModels, Model, ORM } from 'redux-orm'; // Model export class Test extends Model { @@ -22,9 +22,9 @@ export interface FetchIndicatorState { } // id attr is added automatically by redux-orm therefore we have IORMId interface -export type TestState = ITableState; +export type TestState = TableState; -export interface TestORMState extends IORMCommonState { +export interface TestORMState extends ORMCommonState { Test: TestState; } @@ -66,9 +66,8 @@ interface RootState { } export const makeGetTestDisplayList = () => { - const ormSelector = createSelectorORM(orm, (session: ISession) => - session.Test - .all() + const ormSelector = createSelectorORM(orm, (session: SessionWithModels) => + (session.Test.all() as QuerySet) .toRefArray() .map((item) => ({ ...item })) ); diff --git a/types/redux-orm/tsconfig.json b/types/redux-orm/tsconfig.json index d0db87216d..f981bceb20 100644 --- a/types/redux-orm/tsconfig.json +++ b/types/redux-orm/tsconfig.json @@ -7,6 +7,7 @@ "noImplicitAny": true, "noImplicitThis": true, "strictNullChecks": true, + "strictFunctionTypes": true, "baseUrl": "../", "typeRoots": [ "../"