Skip to content

Commit f361156

Browse files
authored
chore: Remove any (#11)
* name map * update ts * fix ts
1 parent 35bf541 commit f361156

File tree

6 files changed

+105
-78
lines changed

6 files changed

+105
-78
lines changed

src/interface.ts

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { ReducerAction } from './useForm';
33
export type InternalNamePath = (string | number)[];
44
export type NamePath = string | number | InternalNamePath;
55

6+
type StoreBaseValue = string | number | boolean;
7+
export type StoreValue = StoreBaseValue | Store | StoreBaseValue[];
68
export interface Store {
7-
[name: string]: any;
9+
[name: string]: StoreValue;
810
}
911

1012
export interface Meta {
@@ -70,6 +72,12 @@ export type RuleObject = BaseRule | ArrayRule;
7072

7173
export type Rule = RuleObject | RuleRender;
7274

75+
export interface ValidateErrorEntity {
76+
values: Store;
77+
errorFields: { name: InternalNamePath; errors: string[] };
78+
outOfDate: boolean;
79+
}
80+
7381
export interface FieldEntity {
7482
onStoreChange: (store: any, namePathList: InternalNamePath[] | null, info: NotifyInfo) => void;
7583
isFieldTouched: () => boolean;
@@ -165,50 +173,51 @@ export type InternalFormInstance = Omit<FormInstance, 'validateFields'> & {
165173
getInternalHooks: (secret: string) => InternalHooks | null;
166174
};
167175

176+
type ValidateMessage = string | (() => string);
168177
export interface ValidateMessages {
169-
default?: string;
170-
required?: string;
171-
enum?: string;
172-
whitespace?: string;
178+
default?: ValidateMessage;
179+
required?: ValidateMessage;
180+
enum?: ValidateMessage;
181+
whitespace?: ValidateMessage;
173182
date?: {
174-
format?: string;
175-
parse?: string;
176-
invalid?: string;
183+
format?: ValidateMessage;
184+
parse?: ValidateMessage;
185+
invalid?: ValidateMessage;
177186
};
178187
types?: {
179-
string?: string;
180-
method?: string;
181-
array?: string;
182-
object?: string;
183-
number?: string;
184-
date?: string;
185-
boolean?: string;
186-
integer?: string;
187-
float?: string;
188-
regexp?: string;
189-
email?: string;
190-
url?: string;
191-
hex?: string;
188+
string?: ValidateMessage;
189+
method?: ValidateMessage;
190+
array?: ValidateMessage;
191+
object?: ValidateMessage;
192+
number?: ValidateMessage;
193+
date?: ValidateMessage;
194+
boolean?: ValidateMessage;
195+
integer?: ValidateMessage;
196+
float?: ValidateMessage;
197+
regexp?: ValidateMessage;
198+
email?: ValidateMessage;
199+
url?: ValidateMessage;
200+
hex?: ValidateMessage;
192201
};
193202
string?: {
194-
len?: string;
195-
min?: string;
196-
max?: string;
197-
range?: string;
203+
len?: ValidateMessage;
204+
min?: ValidateMessage;
205+
max?: ValidateMessage;
206+
range?: ValidateMessage;
198207
};
199208
number?: {
200-
len?: string;
201-
min?: string;
202-
max?: string;
203-
range?: string;
209+
len?: ValidateMessage;
210+
min?: ValidateMessage;
211+
max?: ValidateMessage;
212+
range?: ValidateMessage;
204213
};
205214
array?: {
206-
len?: string;
207-
min?: string;
208-
max?: string;
209-
range?: string;
215+
len?: ValidateMessage;
216+
min?: ValidateMessage;
217+
max?: ValidateMessage;
218+
range?: ValidateMessage;
210219
};
211220
pattern?: {
212-
mismatch?: string;
221+
mismatch?: ValidateMessage;
213222
};
214223
}

src/useForm.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
ValidateMessages,
1616
InternalValidateFields,
1717
InternalFormInstance,
18+
ValidateErrorEntity,
1819
} from './interface';
1920
import { HOOK_MARK } from './FieldContext';
2021
import { allPromiseFinish } from './utils/asyncUtil';
@@ -470,13 +471,15 @@ export class FormStore {
470471
this.triggerOnFieldsChange(resultNamePathList);
471472
});
472473

473-
const returnPromise = summaryPromise
474-
.then(() => {
475-
if (this.lastValidatePromise === summaryPromise) {
476-
return this.store;
477-
}
478-
return Promise.reject([]);
479-
})
474+
const returnPromise: Promise<Store | ValidateErrorEntity | string[]> = summaryPromise
475+
.then(
476+
(): Promise<Store | string[]> => {
477+
if (this.lastValidatePromise === summaryPromise) {
478+
return Promise.resolve(this.store);
479+
}
480+
return Promise.reject([]);
481+
},
482+
)
480483
.catch((results: { name: InternalNamePath; errors: string[] }[]) => {
481484
const errorList = results.filter(result => result && result.errors.length);
482485
return Promise.reject({
@@ -487,9 +490,9 @@ export class FormStore {
487490
});
488491

489492
// Do not throw in console
490-
returnPromise.catch(e => e);
493+
returnPromise.catch<ValidateErrorEntity>(e => e);
491494

492-
return returnPromise;
495+
return returnPromise as Promise<Store | ValidateErrorEntity>;
493496
};
494497
}
495498

src/utils/NameMap.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ interface KV<T> {
99
/**
1010
* NameMap like a `Map` but accepts `string[]` as key.
1111
*/
12-
class NameMap<T = any> {
12+
class NameMap<T> {
1313
private list: KV<T>[] = [];
1414

1515
public clone(): NameMap<T> {
16-
const clone = new NameMap();
16+
const clone: NameMap<T> = new NameMap();
1717
clone.list = this.list.concat();
1818
return clone;
1919
}
@@ -50,12 +50,12 @@ class NameMap<T = any> {
5050
this.list = this.list.filter(item => !matchNamePath(item.key, key));
5151
}
5252

53-
public map(callback: (kv: KV<T>) => any) {
53+
public map<U>(callback: (kv: KV<T>) => U) {
5454
return this.list.map(callback);
5555
}
5656

5757
public toJSON(): { [name: string]: T } {
58-
const json: any = {};
58+
const json: { [name: string]: T } = {};
5959
this.map(({ key, value }) => {
6060
json[key.join('.')] = value;
6161
return null;

src/utils/asyncUtil.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { FieldError } from '../interface';
33
export function allPromiseFinish(promiseList: Promise<FieldError>[]): Promise<FieldError[]> {
44
let hasError = false;
55
let count = promiseList.length;
6-
const results: any[] = [];
6+
const results: FieldError[] = [];
77

88
if (!promiseList.length) {
99
return Promise.resolve([]);

src/utils/validateUtil.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
ValidateOptions,
88
ValidateMessages,
99
RuleObject,
10+
Rule,
11+
StoreValue,
1012
} from '../interface';
1113
import NameMap from './NameMap';
1214
import { containsNamePath, getNamePath, setValues } from './valueUtil';
@@ -16,7 +18,7 @@ import { defaultValidateMessages } from './messages';
1618
* Replace with template.
1719
* `I'm ${name}` + { name: 'bamboo' } = I'm bamboo
1820
*/
19-
function replaceMessage(template: string, kv: { [name: string]: any }): string {
21+
function replaceMessage(template: string, kv: Record<string, string>): string {
2022
return template.replace(/\$\{\w+\}/g, (str: string) => {
2123
const key = str.slice(2, -1);
2224
return kv[key];
@@ -27,20 +29,30 @@ function replaceMessage(template: string, kv: { [name: string]: any }): string {
2729
* We use `async-validator` to validate rules. So have to hot replace the message with validator.
2830
* { required: '${name} is required' } => { required: () => 'field is required' }
2931
*/
30-
function convertMessages(messages: ValidateMessages, name: string, rule: RuleObject) {
31-
const kv: { [name: string]: any } = {
32-
...rule,
32+
function convertMessages(
33+
messages: ValidateMessages,
34+
name: string,
35+
rule: RuleObject,
36+
): ValidateMessages {
37+
const kv = {
38+
...(rule as Record<string, string | number>),
3339
name,
3440
enum: (rule.enum || []).join(', '),
3541
};
3642

37-
const replaceFunc = (template: string, additionalKV?: Record<string, any>) => {
43+
const replaceFunc = (template: string, additionalKV?: Record<string, string>) => {
3844
if (!template) return null;
3945
return () => replaceMessage(template, { ...kv, ...additionalKV });
4046
};
4147

4248
/* eslint-disable no-param-reassign */
43-
function fillTemplate(source: { [name: string]: any }, target: { [name: string]: any } = {}) {
49+
type Template =
50+
| {
51+
[name: string]: string | (() => string) | { [name: string]: Template };
52+
}
53+
| string;
54+
55+
function fillTemplate(source: Template, target: Template = {}) {
4456
Object.keys(source).forEach(ruleName => {
4557
const value = source[ruleName];
4658
if (typeof value === 'string') {
@@ -57,12 +69,12 @@ function convertMessages(messages: ValidateMessages, name: string, rule: RuleObj
5769
}
5870
/* eslint-enable */
5971

60-
return fillTemplate(setValues({}, defaultValidateMessages, messages));
72+
return fillTemplate(setValues({}, defaultValidateMessages, messages)) as ValidateMessages;
6173
}
6274

6375
async function validateRule(
6476
name: string,
65-
value: any,
77+
value: StoreValue,
6678
rule: RuleObject,
6779
options: ValidateOptions,
6880
): Promise<string[]> {
@@ -78,7 +90,7 @@ async function validateRule(
7890
[name]: [cloneRule],
7991
});
8092

81-
const messages = convertMessages(options.validateMessages, name, cloneRule);
93+
const messages: ValidateMessages = convertMessages(options.validateMessages, name, cloneRule);
8294
validator.messages(messages);
8395

8496
let result = [];
@@ -94,13 +106,13 @@ async function validateRule(
94106
: message),
95107
);
96108
} else {
97-
result = [messages.default()];
109+
result = [(messages.default as (() => string))()];
98110
}
99111
}
100112

101113
if (!result.length && subRuleField) {
102114
const subResults: string[][] = await Promise.all(
103-
value.map((subValue: any, i: number) =>
115+
(value as StoreValue[]).map((subValue: StoreValue, i: number) =>
104116
validateRule(`${name}.${i}`, subValue, subRuleField, options),
105117
),
106118
);
@@ -117,7 +129,7 @@ async function validateRule(
117129
*/
118130
export function validateRules(
119131
namePath: InternalNamePath,
120-
value: any,
132+
value: StoreValue,
121133
rules: RuleObject[],
122134
options: ValidateOptions,
123135
) {
@@ -132,7 +144,7 @@ export function validateRules(
132144
}
133145
return {
134146
...currentRule,
135-
validator(rule: any, val: any, callback: any) {
147+
validator(rule: Rule, val: StoreValue, callback: (error?: string) => void) {
136148
let hasPromise = false;
137149

138150
// Wrap callback only accept when promise not provided

src/utils/valueUtil.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import setIn from 'lodash/fp/set';
22
import get from 'lodash/get';
3-
import { InternalNamePath, NamePath, Store } from '../interface';
3+
import { InternalNamePath, NamePath, Store, StoreValue } from '../interface';
44
import { toArray } from './typeUtil';
55

66
/**
@@ -19,12 +19,12 @@ export function getValue(store: Store, namePath: InternalNamePath) {
1919
return value;
2020
}
2121

22-
export function setValue(store: any, namePath: InternalNamePath, value: any) {
22+
export function setValue(store: Store, namePath: InternalNamePath, value: StoreValue): Store {
2323
const newStore = setIn(namePath, value, store);
2424
return newStore;
2525
}
2626

27-
export function cloneByNamePathList(store: any, namePathList: InternalNamePath[]) {
27+
export function cloneByNamePathList(store: Store, namePathList: InternalNamePath[]) {
2828
let newStore = {};
2929
namePathList.forEach(namePath => {
3030
const value = getValue(store, namePath);
@@ -38,32 +38,36 @@ export function containsNamePath(namePathList: InternalNamePath[], namePath: Int
3838
return namePathList && namePathList.some(path => matchNamePath(path, namePath));
3939
}
4040

41-
function isObject(obj: any) {
41+
function isObject(obj: StoreValue) {
4242
return typeof obj === 'object' && obj !== null;
4343
}
4444

4545
/**
4646
* Copy values into store and return a new values object
4747
* ({ a: 1, b: { c: 2 } }, { a: 4, b: { d: 5 } }) => { a: 4, b: { c: 2, d: 5 } }
4848
*/
49-
function internalSetValues(store: Store | any[], values: Store | any[] = {}) {
50-
const isArray: boolean = Array.isArray(store);
51-
const newStore = isArray ? [...(store as any)] : { ...store };
49+
function internalSetValues<T>(store: T, values: T): T {
50+
const newStore: T = (Array.isArray(store) ? [...store] : { ...store }) as T;
51+
52+
if (!values) {
53+
return newStore;
54+
}
55+
5256
Object.keys(values).forEach(key => {
5357
const prevValue = newStore[key];
5458
const value = values[key];
5559

5660
// If both are object (but target is not array), we use recursion to set deep value
5761
const recursive = isObject(prevValue) && isObject(value) && !Array.isArray(value);
58-
newStore[key] = recursive ? internalSetValues(prevValue, value) : value;
62+
newStore[key] = recursive ? internalSetValues(prevValue, value || {}) : value;
5963
});
6064

6165
return newStore;
6266
}
6367

64-
export function setValues(store: Store, ...restValues: Store[]) {
68+
export function setValues<T>(store: T, ...restValues: T[]): T {
6569
return restValues.reduce(
66-
(current: Store, newStore: Store) => internalSetValues(current, newStore),
70+
(current: T, newStore: T): T => internalSetValues<T>(current, newStore),
6771
store,
6872
);
6973
}
@@ -79,7 +83,8 @@ export function matchNamePath(
7983
}
8084

8185
// Like `shallowEqual`, but we not check the data which may cause re-render
82-
export function isSimilar(source: any, target: any) {
86+
type SimilarObject = string | number | {};
87+
export function isSimilar(source: SimilarObject, target: SimilarObject) {
8388
if (source === target) {
8489
return true;
8590
}
@@ -107,12 +112,10 @@ export function isSimilar(source: any, target: any) {
107112
});
108113
}
109114

110-
export function defaultGetValueFromEvent(...args: any[]) {
111-
const arg = args[0];
112-
113-
if (arg && arg.target && 'value' in arg.target) {
114-
return arg.target.value;
115+
export function defaultGetValueFromEvent(event: Event) {
116+
if (event && event.target && 'value' in event.target) {
117+
return (event.target as HTMLInputElement).value;
115118
}
116119

117-
return arg;
120+
return event;
118121
}

0 commit comments

Comments
 (0)