您现在的位置是:首页 > 文章详情

强烈推荐:15道TypeScript练习题 [中篇]

日期:2020-07-26点击:428

写在开头

  • 本次 TypeScript一共有15道题,由易道难,可以说是涵盖了所有的使用场景,入门容易,精通难
  • 之前的上集有8道题,没有看过的小伙伴,可以看这之前的文章:
  • 最近技术团队会马上入驻公众号,后期原创文章会不断增多,广告也有,但是大家请理解,这也是创作的动力,大部分收入是会用来发福利,上次就发了一百本书.有的广告还是可以白嫖的课程,点击进去看看也挺好
  • 强烈推荐:15道优秀的TypeScript练习题   (上集)

正式开始

  • 第八题,模拟动态返回数据,我使用的是泛型解题,此时不是最优解法, AdminsApiResponseDatesApiResponse可以进一步封装抽象成一个接口.有兴趣的可以继续优化

interface User {
  type'user';
  name: string;
  age: number;
  occupation: string;
}

interface Admin {
  type'admin';
  name: string;
  age: number;
  role: string;
}

type responseData = Date;

type Person = User | Admin;

const admins: Admin[] = [
  { type'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
  { type'admin', name: 'Bruce Willis', age: 64, role: 'World saver' },
];

const users: User[] = [
  {
    type'user',
    name: 'Max Mustermann',
    age: 25,
    occupation: 'Chimney sweep',
  },
  { type'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' },
];

type AdminsApiResponse<T> =
  | {
      status: 'success';
      data: T[];
    }
  | {
      status: 'error';
      error: string;
    };


type DatesApiResponse<T> =
  | {
      status: 'success';
      data: T;
    }
  | {
      status: 'error';
      error: string;
    };

function requestAdmins(callback: (response: AdminsApiResponse<Admin>) => void) {
  callback({
    status: 'success',
    data: admins,
  });
}

function requestUsers(callback: (response: AdminsApiResponse<User>) => void) {
  callback({
    status: 'success',
    data: users,
  });
}

function requestCurrentServerTime(
  callback: (response: DatesApiResponse<number>) => void
) {
  callback({
    status: 'success',
    data: Date.now(),
  });
}

function requestCoffeeMachineQueueLength(
  callback: (response: AdminsApiResponse<User>) => void
) {
  callback({
    status: 'error',
    error: 'Numeric value has exceeded Number.MAX_SAFE_INTEGER.',
  });
}

function logPerson(person: Person) {
  console.log(
    ` - ${chalk.green(person.name)}${person.age}, ${
      person.type === 'admin' ? person.role : person.occupation
    }`
  );
}

function startTheApp(callback: (error: Error | null) => void) {
  requestAdmins((adminsResponse) => {
    console.log(chalk.yellow('Admins:'));
    if (adminsResponse.status === 'success') {
      adminsResponse.data.forEach(logPerson);
    } else {
      return callback(new Error(adminsResponse.error));
    }

    console.log();

    requestUsers((usersResponse) => {
      console.log(chalk.yellow('Users:'));
      if (usersResponse.status === 'success') {
        usersResponse.data.forEach(logPerson);
      } else {
        return callback(new Error(usersResponse.error));
      }

      console.log();

      requestCurrentServerTime((serverTimeResponse) => {
        console.log(chalk.yellow('Server time:'));
        if (serverTimeResponse.status === 'success') {
          console.log(
            `   ${new Date(serverTimeResponse.data).toLocaleString()}`
          );
        } else {
          return callback(new Error(serverTimeResponse.error));
        }

        console.log();

        requestCoffeeMachineQueueLength((coffeeMachineQueueLengthResponse) => {
          console.log(chalk.yellow('Coffee machine queue length:'));
          if (coffeeMachineQueueLengthResponse.status === 'success') {
            console.log(`   ${coffeeMachineQueueLengthResponse.data}`);
          } else {
            return callback(new Error(coffeeMachineQueueLengthResponse.error));
          }

          callback(null);
        });
      });
    });
  });
}

startTheApp((e: Error | null) => {
  console.log();
  if (e) {
    console.log(
      `Error: "${e.message}", but it's fine, sometimes errors are inevitable.`
    );
  } else {
    console.log('
Success!');
  }
});
  • 第九题,还是考察泛型, promisify的编写,传入一个返回 promise的函数,函数接受一个参数,这个参数是一个函数,它有对应的根据泛型生成的参数,返回值为 void,同样这个函数的参数也为函数,返回值也为 void

interface User {
    type'user';
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    type'admin';
    name: string;
    age: number;
    role: string;
}

type Person = User | Admin;

const admins: Admin[] = [
    { type'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
    { type'admin', name: 'Bruce Willis', age: 64, role: 'World saver' }
];

const users: User[] = [
    { type'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
    { type'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' }
];

type ApiResponse<T> = (
    {
        status: 'success';
        data: T;
    } |
    {
        status: 'error';
        error: string;
    }
);

function promisify<T>(fn: (callback: (arg: ApiResponse<T>) => void) => void): () => Promise<T> 

function promisify(arg: unknown): unknown {
    return null;
}

const oldApi = {
    requestAdmins(callback: (response: ApiResponse<Admin[]>) => void) {
        callback({
            status: 'success',
            data: admins
        });
    },
    requestUsers(callback: (response: ApiResponse<User[]>) => void) {
        callback({
            status: 'success',
            data: users
        });
    },
    requestCurrentServerTime(callback: (response: ApiResponse<number>) => void) {
        callback({
            status: 'success',
            data: Date.now()
        });
    },
    requestCoffeeMachineQueueLength(callback: (response: ApiResponse<number>) => void) {
        callback({
            status: 'error',
            error: 'Numeric value has exceeded Number.MAX_SAFE_INTEGER.'
        });
    }
};

const api = {
    requestAdmins: promisify(oldApi.requestAdmins),
    requestUsers: promisify(oldApi.requestUsers),
    requestCurrentServerTime: promisify(oldApi.requestCurrentServerTime),
    requestCoffeeMachineQueueLength: promisify(oldApi.requestCoffeeMachineQueueLength)
};

function logPerson(person: Person) {
    console.log(
        ` - ${chalk.green(person.name)}${person.age}${person.type === 'admin' ? person.role : person.occupation}`
    );
}

async function startTheApp() {
    console.log(chalk.yellow('Admins:'));
    (await api.requestAdmins()).forEach(logPerson);
    console.log();

    console.log(chalk.yellow('Users:'));
    (await api.requestUsers()).forEach(logPerson);
    console.log();

    console.log(chalk.yellow('Server time:'));
    console.log(`   ${new Date(await api.requestCurrentServerTime()).toLocaleString()}`);
    console.log();

    console.log(chalk.yellow('Coffee machine queue length:'));
    console.log(`   ${await api.requestCoffeeMachineQueueLength()}`);
}

startTheApp().then(
    () => {
        console.log('Success!');
    },
    (e: Error) => {
        console.log(`Error: "${e.message}", but it's fine, sometimes errors are inevitable.`);
    }
);

  • 第十题,考察 declaer module
declare module 'str-utils' {
  export function strReverse(arg:string): string;
  export function strToLower(arg:string): string;
  export function strToUpper(arg:string): string;
  export function strRandomize(arg:string): string;
  export function strInvertCase(arg:string): string;
}

import {
    strReverse,
    strToLower,
    strToUpper,
    strRandomize,
    strInvertCase
} from 'str-utils';

interface User {
    type'user';
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    type'admin';
    name: string;
    age: number;
    role: string;
}

type Person = User | Admin;

const admins: Admin[] = [
    { type'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
    { type'admin', name: 'Bruce Willis', age: 64, role: 'World saver' },
    { type'admin', name: 'Steve', age: 40, role: 'Steve' },
    { type'admin', name: 'Will Bruces', age: 30, role: 'Overseer' },
    { type'admin', name: 'Superwoman', age: 28, role: 'Customer support' }
];

const users: User[] = [
    { type'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
    { type'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' },
    { type'user', name: 'Moses', age: 70, occupation: 'Desert guide' },
    { type'user', name: 'Superman', age: 28, occupation: 'Ordinary person' },
    { type'user', name: 'Inspector Gadget', age: 31, occupation: 'Undercover' }
];

const isAdmin = (person: Person): person is Admin => person.type === 'admin';
const isUser = (person: Person): person is User => person.type === 'user';

const nameDecorators = [
    strReverse,
    strToLower,
    strToUpper,
    strRandomize,
    strInvertCase
];

function logPerson(person: Person) {
    let additionalInformation: string = '';
    if (isAdmin(person)) {
        additionalInformation = person.role;
    }
    if (isUser(person)) {
        additionalInformation = person.occupation;
    }
    const randomNameDecorator = nameDecorators[
        Math.round(Math.random() * (nameDecorators.length - 1))
    ];
    const name = randomNameDecorator(person.name);
    console.log(
        ` - ${chalk.green(name)}${person.age}${additionalInformation}`
    );
}

([] as Person[])
    .concat(users, admins)
    .forEach(logPerson);
  • 第十一题,我使用了泛型和 declare module解题,如果你有更优解法,可以跟我聊聊,自认为这题没毛病.上面那道题我说两个 interface可以进一步优化,也可以参考这个思路
type func = <T>(input: T[], comparator: (a: T, b: T) => number) => T | null;
type index<L> = <T>(input: T[], comparator: (a: T, b: T) => number) => L;
declare module 'stats' {
  export const getMaxIndex: index<number>;
  export const getMaxElement: func;
  export const getMinIndex: index<number>;
  export const getMinElement: func;
  export const getMedianIndex: index<number>;
  export const getMedianElement: func;
  export const getAverageValue: func;
}

import {
    getMaxIndex,
    getMaxElement,
    getMinIndex,
    getMinElement,
    getMedianIndex,
    getMedianElement,
    getAverageValue
} from 'stats';


interface User {
    type'user';
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    type'admin';
    name: string;
    age: number;
    role: string;
}

const admins: Admin[] = [
    { type'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
    { type'admin', name: 'Bruce Willis', age: 64, role: 'World saver' },
    { type'admin', name: 'Steve', age: 40, role: 'Steve' },
    { type'admin', name: 'Will Bruces', age: 30, role: 'Overseer' },
    { type'admin', name: 'Superwoman', age: 28, role: 'Customer support' }
];

const users: User[] = [
    { type'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
    { type'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' },
    { type'user', name: 'Moses', age: 70, occupation: 'Desert guide' },
    { type'user', name: 'Superman', age: 28, occupation: 'Ordinary person' },
    { type'user', name: 'Inspector Gadget', age: 31, occupation: 'Undercover' }
];

function logUser(user: User | null) {
    if (!user) {
        console.log(' - none');
        return;
    }
    const pos = users.indexOf(user) + 1;
    console.log(` - #${pos} User: ${chalk.green(user.name)}, ${user.age}, ${user.occupation}`);
}

function logAdmin(admin: Admin | null) {
    if (!admin) {
        console.log(' - none');
        return;
    }
    const pos = admins.indexOf(admin) + 1;
    console.log(` - #${pos} Admin: ${chalk.green(admin.name)}, ${admin.age}, ${admin.role}`);
}

const compareUsers = (a: User, b: User) => a.age - b.age;
const compareAdmins = (a: Admin, b: Admin) => a.age - b.age;
const colorizeIndex = (value: number) => chalk.red(String(value + 1));

console.log(chalk.yellow('Youngest user:'));
logUser(getMinElement(users, compareUsers));
console.log(` - was ${colorizeIndex(getMinIndex(users, compareUsers))}th to register`);

console.log();

console.log(chalk.yellow('Median user:'));
logUser(getMedianElement(users, compareUsers));
console.log(` - was ${colorizeIndex(getMedianIndex(users, compareUsers))}th to register`);

console.log();

console.log(chalk.yellow('Oldest user:'));
logUser(getMaxElement(users, compareUsers));
console.log(` - was ${colorizeIndex(getMaxIndex(users, compareUsers))}th to register`);

console.log();

console.log(chalk.yellow('Average user age:'));
console.log(` - ${chalk.red(String(getAverageValue(users, ({age}: User) => age)))} years`);

console.log();

console.log(chalk.yellow('Youngest admin:'));
logAdmin(getMinElement(admins, compareAdmins));
console.log(` - was ${colorizeIndex(getMinIndex(users, compareUsers))}th to register`);

console.log();

console.log(chalk.yellow('Median admin:'));
logAdmin(getMedianElement(admins, compareAdmins));
console.log(` - was ${colorizeIndex(getMedianIndex(users, compareUsers))}th to register`);

console.log();

console.log(chalk.yellow('Oldest admin:'));
logAdmin(getMaxElement(admins, compareAdmins));
console.log(` - was ${colorizeIndex(getMaxIndex(users, compareUsers))}th to register`);

console.log();

console.log(chalk.yellow('Average admin age:'));
console.log(` - ${chalk.red(String(getAverageValue(admins, ({age}: Admin) => age)))} years`);

  • 第十二题,考察模块扩充模式和泛型
import 'date-wizard';

declare module 'date-wizard' {
  // Add your module extensions here.
  export function pad<T>(name: T): T;
  export function dateDetails<T>(name: T): { hours: number };
}
//..
import * as dateWizard from 'date-wizard';
import './module-augmentations/date-wizard';


interface User {
    type'user';
    name: string;
    age: number;
    occupation: string;
    registered: Date;
}

interface Admin {
    type'admin';
    name: string;
    age: number;
    role: string;
    registered: Date;
}

type Person = User | Admin;

const admins: Admin[] = [
    { type'admin', name: 'Jane Doe', age: 32, role: 'Administrator', registered: new Date('2016-06-01T16:23:13') },
    { type'admin', name: 'Bruce Willis', age: 64, role: 'World saver', registered: new Date('2017-02-11T12:12:11') },
    { type'admin', name: 'Steve', age: 40, role: 'Steve', registered: new Date('2018-01-05T11:02:30') },
    { type'admin', name: 'Will Bruces', age: 30, role: 'Overseer', registered: new Date('2018-08-12T10:01:24') },
    { type'admin', name: 'Superwoman', age: 28, role: 'Customer support', registered: new Date('2019-03-25T07:51:05') }
];

const users: User[] = [
    { type'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep', registered: new Date('2016-02-15T09:25:13') },
    { type'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut', registered: new Date('2016-03-23T12:47:03') },
    { type'user', name: 'Moses', age: 70, occupation: 'Desert guide', registered: new Date('2017-02-19T17:22:56') },
    { type'user', name: 'Superman', age: 28, occupation: 'Ordinary person', registered: new Date('2018-02-25T19:44:28') },
    { type'user', name: 'Inspector Gadget', age: 31, occupation: 'Undercover', registered: new Date('2019-03-25T09:29:12') }
];

const isAdmin = (person: Person): person is Admin => person.type === 'admin';
const isUser = (person: Person): person is User => person.type === 'user';

function logPerson(person: Person, index: number) {
    let additionalInformation: string = '';
    if (isAdmin(person)) {
        additionalInformation = person.role;
    }
    if (isUser(person)) {
        additionalInformation = person.occupation;
    }
    let registeredAt = dateWizard(person.registered, '{date}.{month}.{year} {hours}:{minutes}');
    let num = `#${dateWizard.pad(index + 1)}`;
    console.log(
        ` - ${num}${chalk.green(person.name)}${person.age}${additionalInformation}${registeredAt}`
    );
}

console.log(chalk.yellow('All users:'));

([] as Person[])
    .concat(users, admins)
    .forEach(logPerson);

console.log();

console.log(chalk.yellow('Early birds:'));

([] as Person[])
    .concat(users, admins)
    .filter((person) => dateWizard.dateDetails(person.registered).hours < 10)
    .forEach(logPerson);

  • 第十三题,略有难度,考察联合类型、类型断言、泛型,由于数据库的查询, find方法可能传入的参数是多种多样的,为了满足以下的 find使用场景,需要定义 Database这个类

interface User {
  _id: number;
  name: string;
  age: number;
  occupation: string;
  registered: string;
}

interface Admin {
  _id: number;
  name: string;
  age: number;
  role: string;
  registered: string;
}


async function testUsersDatabase() {
  const usersDatabase = new Database<User>(path.join(__dirname, 'users.txt'), [
    'name',
    'occupation',
  ]);

  // $eq operator means "===", syntax {fieldName: {$gt: value}}
  // see more https://docs.mongodb.com/manual/reference/operator/query/eq/
  expect(
    (await usersDatabase.find({ occupation: { $eq'Magical entity' } })).map(
      ({ _id }) => _id
    )
  ).to.have.same.members([6, 8]);
  expect(
    (
      await usersDatabase.find({
        age: { $eq: 31 },
        name: { $eq'Inspector Gadget' },
      })
    )[0]._id
  ).to.equal(5);

  // $gt operator means ">", syntax {fieldName: {$gt: value}}
  // see more https://docs.mongodb.com/manual/reference/operator/query/gt/
  expect(
    (await usersDatabase.find({ age: { $gt: 30 } })).map(({ _id }) => _id)
  ).to.have.same.members([3, 5, 6, 8]);

  // $lt operator means "<", syntax {fieldName: {$lt: value}}
  // see more https://docs.mongodb.com/manual/reference/operator/query/lt/
  expect(
    (await usersDatabase.find({ age: { $lt: 30 } })).map(({ _id }) => _id)
  ).to.have.same.members([0, 2, 4, 7]);

  // $and condition is satisfied when all the nested conditions are satisfied: {$and: [condition1, condition2, ...]}
  // see more https://docs.mongodb.com/manual/reference/operator/query/and/
  // These examples return the same result:
  //   usersDatabase.find({age: {$eq: 31}, name: {$eq'Inspector Gadget'}});
  //   usersDatabase.find({$and: [{age: {$eq: 31}}, {name: {$eq'Inspector Gadget'}}]});
  expect(
    (
      await usersDatabase.find({
        $and: [{ age: { $gt: 30 } }, { age: { $lt: 40 } }],
      })
    ).map(({ _id }) => _id)
  ).to.have.same.members([5, 6]);

  // $or condition is satisfied when at least one nested condition is satisfied: {$or: [condition1, condition2, ...]}
  // see more https://docs.mongodb.com/manual/reference/operator/query/or/
  expect(
    (
      await usersDatabase.find({
        $or: [{ age: { $gt: 90 } }, { age: { $lt: 30 } }],
      })
    ).map(({ _id }) => _id)
  ).to.have.same.members([0, 2, 4, 7, 8]);

  // $text operator means full text search. For simplicity this means finding words from the full-text search
  // fields which are specified in the Database constructor. No stemming or language processing other than
  // being case insensitive is not required.
  // Syntax {$text'Hello World'} - this return all records having both words in its full-text search fields.
  // It is also possible that queried words are spread among different full-text search fields.
  expect(
    (await usersDatabase.find({ $text'max' })).map(({ _id }) => _id)
  ).to.have.same.members([0, 7]);
  expect(
    (await usersDatabase.find({ $text'Hey' })).map(({ _id }) => _id)
  ).to.have.same.members([]);

  // $in operator checks if entry field value is within the specified list of accepted values.
  // Syntax {fieldName: {$in: [value1, value2, value3]}}
  // Equivalent to {$or: [{fieldName: {$eq: value1}}, {fieldName: {$eq: value2}}, {fieldName: {$eq: value3}}]}
  // see more https://docs.mongodb.com/manual/reference/operator/query/in/
  expect(
    (await usersDatabase.find({ _id: { $in: [0, 1, 2] } })).map(
      ({ _id }) => _id
    )
  ).to.have.same.members([0, 2]);
  expect(
    (await usersDatabase.find({ age: { $in: [31, 99] } })).map(({ _id }) => _id)
  ).to.have.same.members([5, 8]);
}

async function testAdminsDatabase() {
  const adminsDatabase = new Database<Admin>(
    path.join(__dirname, 'admins.txt'),
    ['name''role']
  );

  expect(
    (await adminsDatabase.find({ role: { $eq'Administrator' } })).map(
      ({ _id }) => _id
    )
  ).to.have.same.members([0, 6]);
  expect(
    (
      await adminsDatabase.find({
        age: { $eq: 51 },
        name: { $eq'Bill Gates' },
      })
    )[0]._id
  ).to.equal(7);

  expect(
    (await adminsDatabase.find({ age: { $gt: 30 } })).map(({ _id }) => _id)
  ).to.have.same.members([0, 2, 3, 6, 7, 8]);

  expect(
    (await adminsDatabase.find({ age: { $lt: 30 } })).map(({ _id }) => _id)
  ).to.have.same.members([5]);

  expect(
    (
      await adminsDatabase.find({
        $and: [{ age: { $gt: 30 } }, { age: { $lt: 40 } }],
      })
    ).map(({ _id }) => _id)
  ).to.have.same.members([0, 8]);

  expect(
    (
      await adminsDatabase.find({
        $or: [{ age: { $lt: 30 } }, { age: { $gt: 60 } }],
      })
    ).map(({ _id }) => _id)
  ).to.have.same.members([2, 5]);

  expect(
    (await adminsDatabase.find({ $text'WILL' })).map(({ _id }) => _id)
  ).to.have.same.members([4, 6]);
  expect(
    (await adminsDatabase.find({ $text'Administrator' })).map(
      ({ _id }) => _id
    )
  ).to.have.same.members([0, 6]);
  expect(
    (await adminsDatabase.find({ $text'Br' })).map(({ _id }) => _id)
  ).to.have.same.members([]);

  expect(
    (await adminsDatabase.find({ _id: { $in: [0, 1, 2, 3] } })).map(
      ({ _id }) => _id
    )
  ).to.have.same.members([0, 2, 3]);
  expect(
    (await adminsDatabase.find({ age: { $in: [30, 28] } })).map(
      ({ _id }) => _id
    )
  ).to.have.same.members([4, 5]);
}

Promise.all([testUsersDatabase(), testAdminsDatabase()]).then(
  () => console.log('All tests have succeeded, congratulations!'),
  (e) => console.error(e.stack)
);


//Database 

import * as fs from 'fs';

export type FieldOp =
  | { $eq: string | number }
  | { $gt: string | number }
  | { $lt: string | number }
  | { $in: (string | number)[] };

export type Query =
  | { $and: Query[] }
  | { $or: Query[] }
  | { $text: string }
  | ({ [field: string]: FieldOp } & {
      $and?: never;
      $or?: never;
      $text?: never;
    });

function matchOp(op: FieldOp, v: any) {
  if ('$eq' in op) {
    return v === op['$eq'];
  } else if ('$gt' in op) {
    return v > op['$gt'];
  } else if ('$lt' in op) {
    return v < op['$lt'];
  } else if ('$in' in op) {
    return op['$in'].includes(v);
  }
  throw new Error(`Unrecognized op: ${op}`);
}

function matches(q: Query, r: unknown): boolean {
  if ('$and' in q) {
    return q.$and!.every((subq) => matches(subq, r));
  } else if ('$or' in q) {
    return q.$or!.some((subq) => matches(subq, r));
  } else if ('$text' in q) {
    const words = q.$text!.toLowerCase().split(' ');
    return words.every((w) => (r as any).$index[w]);
  }
  return Object.entries(q).every(([k, v]) => matchOp(v, (r as any)[k]));
}

export class Database<T> {
  protected filename: string;
  protected fullTextSearchFieldNames: string[];
  protected records: T[];

  constructor(filename: string, fullTextSearchFieldNames: string[]) {
    this.filename = filename;
    this.filename = filename;
    this.fullTextSearchFieldNames = fullTextSearchFieldNames;
    this.fullTextSearchFieldNames = fullTextSearchFieldNames;

    const text = fs.readFileSync(filename, 'utf8');
    const lines = text.split('\n');
    this.records = lines
      .filter((line) => line.startsWith('E'))
      .map((line) => JSON.parse(line.slice(1)))
      .map((obj) => {
        obj.$index = {};
        for (const f of fullTextSearchFieldNames) {
          const text = obj[f];
          for (const word of text.split(' ')) {
            obj.$index[word.toLowerCase()] = true;
          }
        }
        return obj;
      });
  }
  async find(query: Query): Promise<T[]> {
    return this.records.filter((r) => matches(query, r));
  }
}


写在最后

  • 我是 Peter酱,前端架构师 擅长跨平台和极限场景性能优化 不定期会给你们推送高质量原创文章,公众号回复: 加群即可加入群聊
  • 我把我的往期文章、源码都放在一个仓库了,手写 vue React webpack weboscket redis 静态资源服务器(实现 http缓存) redux promise react-redux 微前端框架 ssr等,进阶前端专家不可或缺.
  • 前端巅峰】即将迎来技术团队入驻,为打造更多前端技术专而奋斗.记得点个 关注在看

本文分享自微信公众号 - 前端巅峰(Java-Script-)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

原文链接:https://my.oschina.net/u/4594011/blog/4438256
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章