TypeScript中的keyof、typeof、索引访问类型、条件类型

2023-11-07

一、keyof类型操作符

TypeScript中的keyof类型操作符可以获取某个类型的所有属性名组成的联合类型。这个操作符的作用是帮助开发者在静态类型检查中更准确地操作属性名。

举例来说,如果我们有如下一个接口:

interface Person {
  name: string;
  age: number;
  gender: 'male' | 'female';
}

我们可以使用keyof来获取这个接口的属性名联合类型:

type PersonKeys = keyof Person;
// 等价于:
// type PersonKeys = 'name' | 'age' | 'gender'

有了属性名联合类型,我们可以在编写代码时更准确地操作属性名。以下是一些使用keyof的实际应用:

1. 动态获取对象的属性值

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

const person: Person = { name: 'Lucy', age: 18, gender: 'female' };
const name = getProperty(person, 'name'); // 类型为string
const age = getProperty(person, 'age'); // 类型为number
const gender = getProperty(person, 'gender'); // 类型为'male' | 'female'

在这个例子中,getProperty函数的第一个参数是一个泛型类型的对象,第二个参数是对象的属性名。由于我们使用了keyof,所以在编写代码时我们可以确定属性名的类型,并且编译器也可以在编译时进行类型检查,保证我们不会误操作属性名或者试图访问不存在的属性。

2. 限制对象的属性种类

function createUser<Keys extends keyof Person>(name: string, value: Person[Keys]): Person {
  const user: Person = { name, age: 0, gender: 'male' };
  user[key] = value; // 编译器知道key是Person的属性名之一,不会有任何错误
  return user;
}

const newUser = createUser('Tom', 'male'); // 类型为Person
const errorUser = createUser('Jack', 'unknown'); // 编译错误

在这个例子中,createUser函数通过泛型限制了属性名的类型,而属性名的类型只能从Person的属性名中取值。在函数内部,我们可以安全地使用key来访问person对象的属性,因为key的类型是Person的属性名之一。如果我们试图传入一个不合法的属性名,编译器会及时提示错误。

3. 避免硬编码属性名

class User {
  constructor(private data: Person) {}

  get<K extends keyof Person>(key: K): Person[K] {
    return this.data[key];
  }
}

const user = new User({ name: 'Lucy', age: 18, gender: 'female' });
const name = user.get('name'); // 类型为string
const age = user.get('age'); // 类型为number
const gender = user.get('gender'); // 类型为'male' | 'female'

在这个例子中,User类接受一个Person对象作为构造函数的参数,同时提供了一个get方法来获取属性值。我们使用了泛型和keyof,这样在代码中就不需要硬编码属性名,避免了潜在的错误。泛型的约束可以帮助我们在编译时确保只能传入合法的属性名。

二、typeof类型操作符

TypeScript中的typeof类型操作符可以用来获取一个值的类型信息,它返回一个代表该值类型的字符串。typeof操作符不会运行代码,只会在编译时进行类型检查。

使用typeof类型操作符的场景包括:

1. 类型检查:可以用来检查变量的类型。例如,可以使用typeof操作符来检查变量是不是一个字符串。

let str = 'hello world';
if (typeof str === 'string') {
  console.log('str is a string');
}

2. 类型推断:可以使用typeof来推断函数返回值的类型。

function double(num: number): number {
  return num * 2;
}

let num = 10;
let numDouble = double(num); // numDouble的类型被推断为number

if (typeof numDouble === 'number') {
  console.log('numDouble is a number');
}

3. 编写工具函数:可以使用typeof来编写工具函数,比如判断一个值是不是一个数组。

function isArray(value: any): value is Array<any> {
  return typeof value === 'object' && value !== null && Array.isArray(value);
}

let arr = [1, 2, 3];
if (isArray(arr)) {
  console.log('arr is an array');
}

4. 简化重复代码:可以使用typeof来简化重复代码,比如初始化一个对象中的属性值。

interface Person {
  name: string;
  age: number;
}

function createPerson(name: string, age: number): Person {
  return {
    name,
    age,
    id: typeof name === 'string' ? name.slice(0, 3).toUpperCase() + age.toString() : '',
  };
}

let person = createPerson('John', 30);
console.log(person.id); // JOH30

总之,typeof类型操作符在TypeScript中有很多用途,可以帮助开发者更好地编写类型安全的代码。

三、索引访问类型

索引访问类型在TypeScript中是一种用于获取类型中属性或元素的方式,它通过字符串或数字索引来访问具有下标的类型。它通常用于动态访问对象属性、数组元素和元组元素等。下面我们从多个角度介绍索引访问类型并举例说明。

1. 动态访问对象属性

假设我们有一个Person对象类型,它有两个属性name和age。我们可以通过索引访问类型来动态获取对象的属性值。

type Person = { name: string; age: number };

type Name = Person['name']; // string
type Age = Person['age']; // number

const person: Person = { name: 'John', age: 18 };

function getProperty(obj: Person, key: keyof Person) {
  return obj[key];
}

const name: string = getProperty(person, 'name'); // 'John'
const age: number = getProperty(person, 'age'); // 18

在上述代码中,我们定义了一个Person类型,并使用Person[‘name’]和Person[‘age’]来获取分别获取name和age的类型。我们使用keyof Person类型指定getProperty方法中的key参数只能传递Person对象的属性名。最后我们通过getProperty方法动态获取person对象的属性值。

2. 动态访问数组元素

索引访问类型也可以用于动态访问数组元素。我们可以通过索引类型来获取数组元素的类型,也可以通过keyof Array类型来获取数组的索引类型。

const fruits = ['apple', 'banana', 'orange'];

type Fruit = typeof fruits[number]; // 'apple' | 'banana' | 'orange'
type Index = keyof typeof fruits; // number | "length" | "toString" | "toLocaleString" | "push" | "pop" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight" | "entries" | "forEach" | "keys" | "values"

上述代码中,我们定义了一个数组fruits,并使用typeof fruits[number]和keyof typeof fruits分别获取了它的元素类型和索引类型。

3. 动态访问元组元素

元组是一种特殊的数组类型,其元素类型可以不同。我们可以通过索引访问类型来动态访问元组元素。

type Tuple = [string, number];

type First = Tuple[0]; // string
type Second = Tuple[1]; // number

const tuple: Tuple = ['hello', 123];

function getTupleElement<T extends ReadonlyArray<any>, U extends keyof T>(
  tuple: T,
  index: U,
): T[U] {
  return tuple[index];
}

const first: string = getTupleElement(tuple, 0); // 'hello'
const second: number = getTupleElement(tuple, 1); // 123

在上述代码中,我们定义了一个元组类型Tuple,通过Tuple[0]和Tuple[1]分别获取了它的第一个和第二个元素类型。同时,我们定义了一个getTupleElement方法,使用泛型T和U分别表示元组类型和索引类型,并通过T[U]获取元组指定索引处的元素。

总之,索引访问类型可以用于动态访问对象属性、数组元素和元组元素。它可以方便地处理动态类型,增强了TypeScript的灵活性和适用性。

四、条件类型

TypeScript中的条件类型可以根据某个类型的特定属性或条件,选择不同的类型。条件类型是TypeScript高级类型中的一种,可以用于定义泛型的约束条件,从而增强代码的类型安全性和灵活性。

下面从不同角度举例分析说明TypeScript中的条件类型:

1. 根据属性判断是否可选

条件类型可以根据某个属性是否存在或者是否可选来确定不同的类型。例如,以下代码中,当T中的K属性为可选属性时,返回Partial类型;当K为必选属性时,返回T本身:

type MyType<T, K extends keyof T> = K extends keyof T ? Partial<T> : T;

2. 根据属性值判断是否满足条件

条件类型可以根据某个属性的值是否满足条件来确定不同的类型。例如,以下代码中,当T中的K属性的类型为U时,返回T本身;否则返回never类型:

type MyType<T, K extends keyof T, U> = T[K] extends U ? T : never;

3. 根据类型之间的关系判断是否满足条件

条件类型可以根据不同类型之间的关系来确定不同的类型。例如,以下代码中,当T为U的子类型时,返回T本身;否则返回never类型:

type MyType<T, U> = T extends U ? T : never;

4. 根据函数参数类型判断返回值类型

条件类型可以根据函数参数的类型来确定函数返回值类型。例如,以下代码中,当T为函数类型时,返回函数返回值的类型;否则返回never类型:

type MyType<T> = T extends (...args: any[]) => infer R ? R : never;

5. 根据对象类型判断是否有特定属性

条件类型可以根据对象类型中是否含有特定属性来确定不同的类型。例如,以下代码中,当T中含有名为K的属性时,返回T本身;否则返回never类型:

type MyType<T, K> = keyof T extends K ? T : never;

通过以上几个例子,可以看出条件类型在TypeScript中的灵活性和强大的约束能力。条件类型可以根据不同的情况进行不同的判断,从而增强代码的可读性和可维护性。

五、类型推理infer

在TypeScript中,类型推理是一种自动推断变量类型的机制,它可以根据变量的使用上下文以及其值的类型来推断变量的类型。而infer关键字是TypeScript的一种高级类型操作符它可以用来从已知类型中推断出未知类型,让类型推理更加灵活

infer关键字通常在条件类型中使用,其中条件类型可以根据条件来决定返回的类型。infer用于捕获条件类型中的未知类型,然后可以用该类型来进行操作。下面分别从多角度举例说明infer如何使用。

1. 从函数参数中推断类型

在下面的这个例子中,我们可以看到如何使用infer关键字从函数参数中推断出其类型:

type ParameterType<T extends (...args: any) => any> = T extends ((arg: infer P) => any) ? P : never;

function foo(param: string) {}

type ParamType = ParameterType<typeof foo>; // string

在这个例子中,我们定义了一个ParameterType类型,它接受一个函数类型作为参数。然后,我们使用infer关键字来推断函数类型的参数类型,并将此类型指定为类型别名ParamType的值。

2. 从数组或元组中推断类型

在下面的这个例子中,我们可以看到如何使用infer关键字从数组或元组中推断出其类型:

type ArrayType<T> = T extends Array<infer U> ? U : never;
type TupleType<T> = T extends [infer U, ...infer V] ? [U, ...V] : never;

type A = ArrayType<number[]>; // number
type B = TupleType<[string, number, boolean]>; // [string, number, boolean]

在这个例子中,我们定义了两个类型别名ArrayType和TupleType。ArrayType接受一个数组类型作为参数,使用infer关键字推断出数组元素的类型,并将其作为其返回类型。TupleType接受一个元组类型作为参数,使用infer关键字推断出元组中第一个元素的类型,并使用剩余类型推断出元组剩余的元素类型。然后,我们分别将这些类型应用于变量A和变量B,得到相应的类型结果。

3. 从Promise中推断类型

在下面的这个例子中,我们可以看到如何使用infer关键字从Promise中推断出其类型:

type PromiseType<T> = T extends Promise<infer U> ? U : never;

async function foo(): Promise<string> {
  return 'hello';
}

type FooType = PromiseType<ReturnType<typeof foo>>; // string

在这个例子中,我们定义了一个PromiseType类型,它接受一个Promise类型作为参数,使用infer关键字推断出Promise的值类型,并将其作为其返回类型。然后,我们定义了一个异步函数foo,其返回类型为Promise。最后,我们将函数foo的ReturnType应用于PromiseType类型,并得到其返回值类型为string的结果。

总之,infer是TypeScript中一个非常重要的高级类型操作符,可以用于从已知类型中推断出未知类型,让类型推理更加灵活。通过上述多个角度的示例,希望可以更好地理解infer在TypeScript中的实际应用。

六、分布式条件类型

分布式条件类型是TypeScript的一项高级特性,它也是条件类型的一种。分布式条件类型可以根据一个类型参数 T,在联合类型中判断 T 是否为其他类型,并根据 T 是该类型或其子集来生成新类型。这个生成过程会在联合类型中遍历每一个元素,并生成对应的类型。与普通的条件类型不同的是,分布式条件类型会把联合类型的操作分发到每一个元素中。

下面我们通过举例分析,更全面地了解分布式条件类型。

1、 基本使用

首先,我们看一个最基本的例子:

type IfNumber<T> = T extends number ? 'yes' : 'no';
type A = IfNumber<1>; // 'yes'
type B = IfNumber<'a'>; // 'no'
type C = IfNumber<number | string>; // 'yes' | 'no'

这里,我们定义了一个条件类型IfNumber,当T是number类型的时候返回’yes’,否则返回’no’。当我们分别传入1、‘a’、number | string三种类型作为类型参数进行测试时,分别返回’yes’、‘no’、‘yes’ | ‘no’。

2、 分布式条件类型在泛型中的应用

分布式条件类型可以用在泛型中,作为泛型约束的一部分。比如,我们可以定义一个函数,用于获取对象的属性值。如果对象的属性值是数字,返回数字类型的对象,否则返回字符串类型的对象。

type ObjectValue<T> = T extends { [key: string]: infer U } ? U : never;
type ObjectWithType<T, U> = { [K in keyof T]: ObjectValue<T[K]> extends U ? T[K] : never };
type ExtractObject<O, U> = ObjectWithType<O, U>[keyof O];

function getPropByType<O, U>(obj: O, type: U): ExtractObject<O, U>[] {
  const result = [];
  for (const key in obj) {
    const value = obj[key];
    if (typeof value === typeof type) {
      result.push(value);
    }
  }
  return result;
}

const obj = {
  a: 1,
  b: '2',
  c: 3,
};
const result = getPropByType(obj, '2');

这里,我们使用分布式条件类型ObjectWithType来定义一个新类型ObjectWithType<T, U>,它可以将T中每个属性值的类型做比较,只有当属性值的类型===U时才保留该属性。同时,我们使用ObjectValue来辅助获取对象属性值的类型。在getPropByType函数中,我们传入一个对象和一个类型参数U,函数会遍历对象的属性值,检查它们的类型是否等于U,并将符合条件的属性值保存在数组中后返回。

3、 分布式条件类型在类型映射中的应用

分布式条件类型还可以用于类型映射中。下面我们使用分布式条件类型,实现一个将对象中所有属性变成可选属性的函数。

type Optionalize<T> =
  T extends any ? {
    [K in keyof T]?: Optionalize<T[K]>;
  } : never;

function optionalize<Key extends string, O extends { [K in Key]: any }>(obj: O): Optionalize<O> {
  const result: Optionalize<O> = {};
  for (const key in obj) {
    const value = obj[key];
    if (typeof value === 'object' && !Array.isArray(value)) {
      result[key] = optionalize(value);
    } else {
      result[key as keyof O] = value;
    }
  }
  return result;
}

const obj = {
  a: {
    b: 1,
    c: {
      d: 2,
    },
  },
  e: '3',
};
const optionalObj = optionalize(obj);

这里,我们使用了分布式条件类型来定义Optionalize类型。它首先认为T可以是任何类型,然后对于T中的每个属性K,我们都将它变成一个可选属性。在optionalize函数中,我们分别遍历了obj的所有属性,并根据value的类型决定是递归处理还是复制value的值到result中,最终返回了一个可选属性合集Optionalize。

分布式条件类型是一项高级特性,它可以对联合类型的所有元素进行操作,生成多样化的新类型。我们在实际场景中可以通过它来解决一些复杂的问题,比如提取对象中某个类型的属性、将对象中的属性转换成可选属性。掌握这个知识点,可以让我们更好地应对类型转换的挑战。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TypeScript中的keyof、typeof、索引访问类型、条件类型 的相关文章

  • 如何测试 javascript 闭包内的函数

    这似乎是不可能的 也可能是 但我正在尝试更多的 TDD 但我总是在闭包方面碰壁 假设我有以下内容 function createSomething init function privateMethod param return init
  • Android 设备上的 PhoneGap 蓝牙插件

    我一直在尝试让 PhoneGap 工作的蓝牙插件 但我似乎不知道哪里出了问题 首先 我的测试设备是 Galaxy S3 GT 19305T 应用程序是使用PhoneGap CLI http docs phonegap com en 3 0
  • 如何重定向到 instagram://user?username={username}

    我的 html 页面上有这个链接 可以在特定用户上打开 Instagram 应用程序 a href Link to Instagram Profile a 我一直在寻找自动运行 url instagram user username USE
  • 如何重置使用 JavaScript 更改的 CSS 属性?

    我的导航按钮的宽度从 100px 增加到 150px 当鼠标悬停在 nav li hover width 150px 但是使用 javascript 我已经做到了 无论选择哪个选项 宽度都将继续为 150px 当选择每个选项时 它会使其他选
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • 如何抑制窗口鼠标滚轮滚动...?

    我正在开发嵌入页面中的画布应用程序 我有它 因此您可以使用鼠标滚轮放大绘图 但不幸的是 这会滚动页面 因为它是文章的一部分 当我在 dom 元素上滚动鼠标滚轮时 是否可以阻止鼠标滚轮在窗口上滚动 附加鼠标滚轮 不是 Gecko DOMMou
  • 除了更改标题之外,如何在 Firefox 中强制另存为对话框?

    有没有办法在 ff 中强制打开 www example com example pdf 的另存为对话框 我无法更改标题 如果您可以将文件以 Base64 格式输出到客户端 则可以使用 data uri 进行下载 location href
  • 为什么是 javascript:history.go(-1);无法在移动设备上工作?

    首先 一些背景 我有一个向用户呈现搜索页面 html 表单 的应用程序 填写标准并单击 搜索 按钮后 结果将显示在标准部分下方 在结果列表中 您可以通过单击将您带到新页面的链接来查看单个结果的详细信息 在详细信息页面中 我添加了一个 返回结
  • 标签获取 href 值

    我有以下 html div class threeimages a img alt Australia src Images Services 20button tcm7 9688 gif a div class text h2 a hre
  • 使用 KnockoutJs 映射插件进行递归模板化

    我正在尝试使用以下方法在树上进行递归模板化ko映射 插入 http knockoutjs com documentation plugins mapping html 但我无法渲染它 除非我定义separate每个级别的模板 在以下情况下
  • Meteor - 从客户端取消服务器方法

    我正在通过服务器方法执行数据库计数 用户可以选择他们希望如何执行计数 然后调用该方法 我的问题是 计数可能需要一些时间 并且用户可能会在方法运行时改变主意并请求不同的计数 有什么方法可以取消调用的方法并运行新的计数吗 我认为 this un
  • 在javascript中解析json - 长数字被四舍五入

    我需要解析一个包含长数字的 json 在 java servlet 中生成 问题是长数字被四舍五入 当执行这段代码时 var s x 6855337641038665531 var obj JSON parse s alert obj x
  • 表单计算器脚本基本价格未加载 OnLoad

    我的表单中有一个计算器来计算我的下拉选项选择 function select calculate on change calc input type checkbox calculate on click calc function cal
  • 提交表单并重定向页面

    我在 SO 上看到了很多与此相关的其他问题 但没有一个对我有用 我正在尝试提交POST表单 然后将用户重定向到另一个页面 但我无法同时实现这两种情况 我可以获取重定向或帖子 但不能同时获取两者 这是我现在所拥有的
  • Typescript导入别名+桶文件

    我最近花了很多时间 因为 Angular ngrx typescript 生态系统中某些事物的特定行为 并且我无法识别可能的根本原因 场景 我已经构建了一些效果 并将它们导出到桶文件中 index ts import MyEffects f
  • 如何使用tampermonkey模拟react应用程序中的点击?

    我正在尝试使用 Tampermonkey 脚本模拟对 React 元素的点击 不幸的是 由于 React 有自己的影子 DOM 所以天真的方法使用document querySelector 不工作 我遇到了一些需要修改 React 组件本
  • 为什么在 Internet Explorer 中访问 localStorage 对象会引发错误?

    我正在解决一个客户端问题 Modernizr 意外地没有检测到对localStorageInternet Explorer 9 中的对象 我的页面正确使用 HTML 5 文档类型 并且开发人员工具报告该页面具有 IE9 的浏览器模式和 IE
  • 模块构建失败(来自 ./node_modules/babel-loader/lib/index.js)Vue Js

    我从 GitHub 下载了一个我和我的朋友正在开发的项目 但是当我尝试运行时 npm run serve 我收到这个错误 src main js 中的错误 Module build failed from node modules babe
  • 为什么我不能在 AngularJS 中使用 data-* 作为指令的属性名称?

    On the t他的笨蛋 http plnkr co edit l3KoY3 p preview您可以注意到属性名称模式的奇怪行为data 在指令中 电话 Test of data named attribute br
  • 如何从图像输入中获取 xy 坐标?

    我有一个输入设置为图像类型

随机推荐

  • C语言《文件操作》事无巨细,保姆级介绍,通俗易懂

    目录 1 文件名与文件分类 2 文件操作使用 2 1文件的打开与关闭 3 文件操作函数 3 1其他文件函数 1 fseek 2 ftell 3 rewind 4 文件结束的判定 4 1被错误使用的 feof 4 2文件结束的正确判断 5 文
  • negix安装部署

    1 从nginx官网下载Nginx wget http nginx org download nginx 1 8 1 tar gz 2 解压Nginx tar zxvf nginx 1 8 1 tar gz 3 初始化配置 configur
  • OpenCV(3.4.1) Error: Assertion failed (scn == 3

    错误 OpenCV 3 4 1 Error Assertion failed scn 3 scn 4 in cv cvtColor file D Build OpenCV opencv 3 4 1 modules imgproc src c
  • vi的一些操作

    1 u可撤销操作 2 yy复制当前行 3 p粘贴复制的行 4 dd删除一行 5 xxx可以定位xxx所在位置 6 n或ngg或nG可以跳转到第n行 以下设置是临时的 只在当前vi中生效 但可将其添加在配置文件 etc virc中使每次按文件
  • STM32CubeMX的使用教程

    STM32 关于STM32CubeMX的使用 打开Cube 点击File New Project 搜索芯片型号这边选择的是STM32L071CB系列上面菜单Docs Resources可以下载数据手册程序手册等 点击Start Projec
  • DEBUG:only Tensors of floating point dtype can require gradients

    DEBUG only Tensors of floating point dtype can require gradients 解决 x V t arange 2 4 float requires grad True
  • 4_hytrix_信号量_线程池

    文章目录 Hystrix 核心特性和原理 使用 单独使用 整合 Feign 整合RestTemplate 信号量与线程隔离 线程池隔离 信号量隔离 常用配置 hystrix 使用dashboard Hystrix 核心特性和原理 熔断 连续
  • C strtok strtok_s 函数说明 按分隔符分解字符串

    1 说明 1 1 函数签名如下 char strtok char str const char delimiters 1 str 要被分解成一组小字符串的字符串 2 delimiters 包含分隔符的 C 字符串 1 2 返回值 该函数返回
  • DPDK的PMD(uio/igb_uio/vfio-pci/uio_pci_generic)

    目录 linux收包的方式 中断对性能的影响有多大 轮询对性能的提升有多大 PMD 介绍 收包对比 内核收包的弊端 DPDK 收包的优点 uio igb uio uio pci generic vfio pci igb uio IGB UI
  • MATLAB算法实战应用案例精讲-【集成算法】集成学习模型stacking(附Python和R语言代码)

    目录 前言 几个高频面试题目 1 哪种集成技术更优 什么情况下选择哪种集成技术呢
  • Java多线程技术详解(全都是细节!)

    多线程启动 线程有两种启动方式 实现Runnable接口 继承Thread类并重写run 方法 1 Thread 与 Runnable Runnable接口表示线程要执行的任务 当Runnable中的run 方法执行时 表示线程在激活状态
  • fisco bcos用caliper0.2.0进行压力测试的安装配置

    一 前期环境 1 硬件 需要外网权限 2 操作系统 版本要求 Ubuntu gt 16 04 CentOS gt 7 MacOS gt 10 14 3 基础软件 python 2 7 make g gcc git sudo apt inst
  • 中医处方软件_重磅上线:中医传承计算平台V3.0正式推出

    重要小贴士 为进一步提高期刊论文质量和水平 更为深度的传承和传播名医经验 中医传承计算平台研发团队联合中药大品种联盟将于2020年7月24 26日在贵阳举办中医药科研论文与SCI写作培训会议 该培训班围绕名医学术思想 经验总结 毕业论文设计
  • win10下MYSQL的下载、安装以及配置超详解教程~~小白入

    下载MYSQL 官网下载MYSQL5 7 21版本 链接地址https www mysql com downloads 下载流程图如下 进入官网点击Community 下载社区版 找到MYSQL Community Server 点击下方D
  • 系统吞吐量、TPS(QPS)、用户并发量、性能测试概念和公式

    一 系统吞度量要素 一个系统的吞度量 承压能力 与request对CPU的消耗 外部接口 IO等等紧密关联 单个reqeust 对CPU消耗越高 外部系统接口 IO影响速度越慢 系统吞吐能力越低 反之越高 系统吞吐量几个重要参数 QPS T
  • stm32 GPIO输入输出

    GPIO 通用输入输出口 可配置为8种输入输出模式 输出模式下可控制端口输出高低电平 用以驱动LED 控制蜂鸣器 模拟通信协议输出时序等 输入模式下可读取端口的高低电平和电压 用于读取按键输入 外接模块电平信号输入 ADC电压采集 模拟通信
  • qt中实现绘制图形与截图

    引言 实现可以选择线型 线宽 颜色 是否填充图形来绘制各种常见的图形 同时可以选择矩形区域来实现截图 效果 绘图的效果如上 截图的效果 实现 项目使用的qt5 13 2 编译器为MSVC2017 64bit 该项目是基于基类QWidget创
  • 多重继承和多继承, super, __mro__

    继承 父类派生子类 子类继承父类 通过继承 可以让子类去拥有父类中的属性和方法 而不必重新编写相同的代码 并且可以在父类的基础上添加新的属性和功能 在继承的同时 子类还可以重写父类中的方法 从而获取与父类不同的功能 实现多态 在 Pytho
  • 【华为OD机试真题 JS】报数游戏

    标题 报数游戏 时间限制 1秒 内存限制 262144K 语言限制 不限 100个人围成一圈 每个人有一个编码 编号从1开始到100 他们从1开始依次报数 报到为M的人自动退出圈圈 然后下一个人接着从1开始报数 直到剩余的人数小于M 请问最
  • TypeScript中的keyof、typeof、索引访问类型、条件类型

    一 keyof类型操作符 TypeScript中的keyof类型操作符可以获取某个类型的所有属性名组成的联合类型 这个操作符的作用是帮助开发者在静态类型检查中更准确地操作属性名 举例来说 如果我们有如下一个接口 interface Pers