百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 博客教程 > 正文

15道优秀的TypeScript练习题(中) typescript基础

connygpt 2024-09-25 15:46 9 浏览

作者:是Peter酱呀

转发链接:https://mp.weixin.qq.com/s/ZR3vbAie-DxGaePngGkI3w

写在开头

  • 本次TypeScript一共有15道题,由易道难,可以说是涵盖了所有的使用场景,入门容易,精通难
  • 之前的上集有8道题,没有看过的小伙伴,可以看这之前的文章:

正式开始

  • 第八题,模拟动态返回数据,我使用的是泛型解题,此时不是最优解法,AdminsApiResponse和DatesApiResponse可以进一步封装抽象成一个接口.有兴趣的可以继续优化
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等,进阶前端专家不可或缺.

作者:是Peter酱呀

转发链接:https://mp.weixin.qq.com/s/ZR3vbAie-DxGaePngGkI3w

相关推荐

3分钟让你的项目支持AI问答模块,完全开源!

hello,大家好,我是徐小夕。之前和大家分享了很多可视化,零代码和前端工程化的最佳实践,今天继续分享一下最近开源的Next-Admin的最新更新。最近对这个项目做了一些优化,并集成了大家比较关注...

干货|程序员的副业挂,12个平台分享

1、D2adminD2Admin是一个完全开源免费的企业中后台产品前端集成方案,使用最新的前端技术栈,小于60kb的本地首屏js加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助...

Github标星超200K,这10个可视化面板你知道几个

在Github上有很多开源免费的后台控制面板可以选择,但是哪些才是最好、最受欢迎的可视化控制面板呢?今天就和大家推荐Github上10个好看又流行的可视化面板:1.AdminLTEAdminLTE是...

开箱即用的炫酷中后台前端开源框架第二篇

#头条创作挑战赛#1、SoybeanAdmin(1)介绍:SoybeanAdmin是一个基于Vue3、Vite3、TypeScript、NaiveUI、Pinia和UnoCSS的清新优...

搭建React+AntDeign的开发环境和框架

搭建React+AntDeign的开发环境和框架随着前端技术的不断发展,React和AntDesign已经成为越来越多Web应用程序的首选开发框架。React是一个用于构建用户界面的JavaScrip...

基于.NET 5实现的开源通用权限管理平台

??大家好,我是为广大程序员兄弟操碎了心的小编,每天推荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节省开发效率,实现不加班不熬夜不掉头发,是我的目标!??今天小编推荐一款基于.NE...

StreamPark - 大数据流计算引擎

使用Docker完成StreamPark的部署??1.基于h2和docker-compose进行StreamPark部署wgethttps://raw.githubusercontent.com/a...

教你使用UmiJS框架开发React

1、什么是Umi.js?umi,中文可发音为乌米,是一个可插拔的企业级react应用框架。你可以将它简单地理解为一个专注性能的类next.js前端框架,并通过约定、自动生成和解析代码等方式来辅助...

简单在线流程图工具在用例设计中的运用

敏捷模式下,测试团队的用例逐渐简化以适应快速的发版节奏,大家很早就开始运用思维导图工具比如xmind来编写测试方法、测试点。如今不少已经不少利用开源的思维导图组件(如百度脑图...)来构建测试测试...

【开源分享】神奇的大数据实时平台框架,让Flink&amp;Spark开发更简单

这是一个神奇的框架,让Flink|Spark开发更简单,一站式大数据实时平台!他就是StreamX!什么是StreamX大数据技术如今发展的如火如荼,已经呈现百花齐放欣欣向荣的景象,实时处理流域...

聊聊规则引擎的调研及实现全过程

摘要本期主要以规则引擎业务实现为例,陈述在陌生业务前如何进行业务深入、调研、技术选型、设计及实现全过程分析,如果你对规则引擎不感冒、也可以从中了解一些抽象实现过程。诉求从硬件采集到的数据提供的形式多种...

【开源推荐】Diboot 2.0.5 发布,自动化开发助理

一、前言Diboot2.0.5版本已于近日发布,在此次发布中,我们新增了file-starter组件,完善了iam-starter组件,对core核心进行了相关优化,让devtools也支持对IAM...

微软推出Copilot Actions,使用人工智能自动执行重复性任务

IT之家11月19日消息,微软在今天举办的Ignite大会上宣布了一系列新功能,旨在进一步提升Microsoft365Copilot的智能化水平。其中最引人注目的是Copilot...

Electron 使用Selenium和WebDriver

本节我们来学习如何在Electron下使用Selenium和WebDriver。SeleniumSelenium是ThoughtWorks提供的一个强大的基于浏览器的开源自动化测试工具...

Quick &#39;n Easy Web Builder 11.1.0设计和构建功能齐全的网页的工具

一个实用而有效的应用程序,能够让您轻松构建、创建和设计个人的HTML网站。Quick'nEasyWebBuilder是一款全面且轻巧的软件,为用户提供了一种简单的方式来创建、编辑...