Move TypedRedux out into a new NPM package called 'redux-typed'

This commit is contained in:
SteveSandersonMS
2016-02-09 11:17:41 -08:00
parent 047d14a6cd
commit b8224d2bef
12 changed files with 158 additions and 67 deletions

View File

@@ -1,67 +0,0 @@
// Credits for the type detection trick: http://www.bluewire-technologies.com/2015/redux-actions-for-typescript/
import * as React from 'react';
import { Dispatch } from 'redux';
import { connect as nativeConnect, ElementClass } from 'react-redux';
interface ActionClass<T extends Action> {
prototype: T;
}
export function typeName(name: string) {
return function<T extends Action>(actionClass: ActionClass<T>) {
// Although we could determine the type name using actionClass.prototype.constructor.name,
// it's dangerous to do that because minifiers may interfere with it, and then serialized state
// might not have the expected meaning after a recompile. So we explicitly ask for a name string.
actionClass.prototype.type = name;
}
}
export function isActionType<T extends Action>(action: Action, actionClass: ActionClass<T>): action is T {
return action.type == actionClass.prototype.type;
}
// Middleware for transforming Typed Actions into plain actions
export const typedToPlain = (store: any) => (next: any) => (action: any) => {
next(Object.assign({}, action));
};
export abstract class Action {
type: string;
constructor() {
// Make it an own-property (not a prototype property) so that it's included when JSON-serializing
this.type = this.type;
}
}
export interface Reducer<TState> extends Function {
(state: TState, action: Action): TState;
}
export interface ActionCreatorGeneric<TState> extends Function {
(dispatch: Dispatch, getState: () => TState): any;
}
interface ClassDecoratorWithProps<TProps> extends Function {
<T extends (typeof ElementClass)>(component: T): T;
props: TProps;
}
type ReactComponentClass<T, S> = new(props: T) => React.Component<T, S>;
class ComponentBuilder<TOwnProps, TActions, TExternalProps> {
constructor(private stateToProps: (appState: any) => TOwnProps, private actionCreators: TActions) {
}
public withExternalProps<TAddExternalProps>() {
return this as any as ComponentBuilder<TOwnProps, TActions, TAddExternalProps>;
}
public get allProps(): TOwnProps & TActions & TExternalProps { return null; }
public connect<TState>(componentClass: ReactComponentClass<TOwnProps & TActions & TExternalProps, TState>): ReactComponentClass<TExternalProps, TState> {
return nativeConnect(this.stateToProps, this.actionCreators as any)(componentClass);
}
}
export function provide<TOwnProps, TActions>(stateToProps: (appState: any) => TOwnProps, actionCreators: TActions) {
return new ComponentBuilder<TOwnProps, TActions, {}>(stateToProps, actionCreators);
}

View File

@@ -0,0 +1,4 @@
/typings/
/node_modules/
/*.js
/*.d.ts

View File

@@ -0,0 +1,3 @@
!/*.js
!/*.d.ts
/typings/

View File

@@ -0,0 +1,12 @@
Copyright (c) .NET Foundation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
these files except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

View File

@@ -0,0 +1 @@
TODO

View File

@@ -0,0 +1,13 @@
{
"name": "redux-typed",
"version": "1.0.0",
"description": "Helpers for building React+Redux apps with strong TypeScript type checking everywhere",
"main": "main.js",
"typings": "main.d.ts",
"scripts": {
"prepublish": "tsd update && tsc && echo 'Finished building NPM package \"redux-typed\"'",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Microsoft",
"license": "Apache-2.0"
}

View File

@@ -0,0 +1,24 @@
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
if (typeof (<any>Object).assign != 'function') {
(function () {
(<any>Object).assign = function (target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
}

View File

@@ -0,0 +1,42 @@
// Credits for the type detection technique: http://www.bluewire-technologies.com/2015/redux-actions-for-typescript/
import * as React from 'react';
import { Dispatch } from 'redux';
import './ObjectAssignPolyfill';
export interface ActionClass<T extends Action> {
prototype: T;
}
export function typeName(name: string) {
return function<T extends Action>(actionClass: ActionClass<T>) {
// Although we could determine the type name using actionClass.prototype.constructor.name,
// it's dangerous to do that because minifiers may interfere with it, and then serialized state
// might not have the expected meaning after a recompile. So we explicitly ask for a name string.
actionClass.prototype.type = name;
}
}
export function isActionType<T extends Action>(action: Action, actionClass: ActionClass<T>): action is T {
return action.type == actionClass.prototype.type;
}
// Middleware for transforming Typed Actions into plain actions
export const typedToPlain = (store: any) => (next: any) => (action: any) => {
next((<any>Object).assign({}, action));
};
export abstract class Action {
type: string;
constructor() {
// Make it an own-property (not a prototype property) so that it's included when JSON-serializing
this.type = this.type;
}
}
export interface Reducer<TState> extends Function {
(state: TState, action: Action): TState;
}
export interface ActionCreatorGeneric<TState> extends Function {
(dispatch: Dispatch, getState: () => TState): any;
}

View File

@@ -0,0 +1,27 @@
import * as React from 'react';
import { connect as nativeConnect, ElementClass } from 'react-redux';
interface ClassDecoratorWithProps<TProps> extends Function {
<T extends (typeof ElementClass)>(component: T): T;
props: TProps;
}
export type ReactComponentClass<T, S> = new(props: T) => React.Component<T, S>;
export class ComponentBuilder<TOwnProps, TActions, TExternalProps> {
constructor(private stateToProps: (appState: any) => TOwnProps, private actionCreators: TActions) {
}
public withExternalProps<TAddExternalProps>() {
return this as any as ComponentBuilder<TOwnProps, TActions, TAddExternalProps>;
}
public get allProps(): TOwnProps & TActions & TExternalProps { return null; }
public connect<TState>(componentClass: ReactComponentClass<TOwnProps & TActions & TExternalProps, TState>): ReactComponentClass<TExternalProps, TState> {
return nativeConnect(this.stateToProps, this.actionCreators as any)(componentClass);
}
}
export function provide<TOwnProps, TActions>(stateToProps: (appState: any) => TOwnProps, actionCreators: TActions) {
return new ComponentBuilder<TOwnProps, TActions, {}>(stateToProps, actionCreators);
}

View File

@@ -0,0 +1,2 @@
export * from './StrongActions';
export * from './StrongProvide';

View File

@@ -0,0 +1,12 @@
{
"compilerOptions": {
"moduleResolution": "node",
"module": "commonjs",
"target": "es5",
"declaration": true,
"outDir": "."
},
"exclude": [
"node_modules"
]
}

View File

@@ -0,0 +1,18 @@
{
"version": "v4",
"repo": "borisyankov/DefinitelyTyped",
"ref": "master",
"path": "typings",
"bundle": "typings/tsd.d.ts",
"installed": {
"react/react.d.ts": {
"commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846"
},
"react-redux/react-redux.d.ts": {
"commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846"
},
"redux/redux.d.ts": {
"commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846"
}
}
}