typescript索引类型_typescript入门:高级类型

学习typescript中 ,有一个小伙伴提出了一个问题

const a = {

a:'1',

b:'2',

c:'3'

}

复制代码

如何取到每个键上的值 ,组成一个联合类型 ? 即得到一个类型为

type forA = "1" | "2" | "3"

复制代码

一位大神给出了答案

const a = {

a:'1',

b:'2',

c:'3'

} as const

type t = T[keyof T]

type forA = t //"1" | "2" | "3"

复制代码

我已经开始迷迷糊糊了。接着提问者又延伸了这个问题

const a = {

a:'1',

b:'2',

c:'3',

d:{

f:'4'

}

}

复制代码

如何取到每个键上的值 (包括一个深层嵌套),组成一个联合类型 ? 即得到一个类型为

type forA = "1" | "2" | "3" | "4"

复制代码

过了一会,大神又拿出了回答

const a = {

a:'1',

b:'2',

c:'3',

d:{

f:'4'

}

} as const

type t = {

[K in keyof T]:T extends object

? t

: T[K]

}[keyof T]

type forA = t //"1" | "2" | "3" | "4"

复制代码

什么?类型里面还有递归!对知识查漏补缺,列下以下几点

定义变量时的 as const

type 内的[K in keyof T]

extends A ? B : C 类型的三目表达式?

类型递归?

最后的 [keyof T]

keyof 和 typeof

keyof 获得接口或者type alias 的键

interface interfaceNumber{

one:string,

two:number

}

type typeNumber = {

three:string,

four:number

}

type interfaceKey = keyof interfaceNumber // "one" | "four"

type numberKey = keyof typeNumber // "three" | "four"

复制代码

typeof使一个上文的某个 Javascript变量 转换为typescript中的类型

const someType = {

obj:{

one:1

},

arr:[1,2,4],

num:1

}

type t = typeof someType

//{

// obj: {

// one: number;

// };

// arr: number[];

// num: number;

//}

复制代码

类型系统递归地把一个对象上键的值转换为对应类型

as const

把一个数字类型或者字符串类型在转换为类型时,缩紧为字面量。

const a = 1 as const;

type a1 = typeof a;// 1

const b = "i am b" as const;

type b1 = typeof b;// "i am b"

const c = [1,"23434" , 1] as const

type c1 = typeof noArray // readonly [1, "23434", 1]

复制代码

如何理解字面量和string类型?字面量也是单独的一个类型,而类型string ,可以理解为无穷(所有)字面量的联合 "a" | "b" | "c"|....

它是字面量的全集。同理number

as const 还可以灵活穿插在对象中使用 , 但是数组不行。

const someType = {

obj:{

one:1 as const

},

num:1

}

//typeof someType

//{

// obj: {

// one: 1;

// };

// num: number;

//}

const Array = [1,2 as const , 1]

//typeof Array

//number[]

复制代码

索引类型 type[key]

索引到interface或者tpye alias 对应键的类型

const someType = {

obj:{

one:1

},

arr:[1,2,4],

num:1

}

type t = typeof someType

type obj = t["obj"]//{ one:number }

interface T{

a:string,

t:{

p:number

}

}

type a = T["a"]//string

type p = T["t"]["p"]//number

复制代码

使用 t.obj 来索引类型是无效的 ,命名空间才可以这么做。

如果索引联合字符串,则结果也是被索引的键的类型的联合。

interface T{

a:string,

b:number

}

type t1 = T["a" | "b"]// string | number

//或者

type t2 = T[ keyof T ]// string | number

复制代码

映射类型[ K in keyof T]

只能在type中用。

type getType1= {

[K in keyof T]: T[K]

}

//报错

//计算属性名的类型必须为 "string"、"number"、"symbol" 或 "any"。ts(2464)

//成员“[K in keyof”隐式包含类型“any”。ts(7008)

interface getType2{

[K in keyof T]: T[K]

}

复制代码

可作为固定的语法 [K in keyof T] ,K表示所有 T 中的键被拆分成一个个键,后面可以声明类型

const someType = {

obj:{

one:1

},

num:2

}

type getType1= {

[K in keyof T]: T[K]

}

type instance1 = getType1

//{

//obj:{

// one:string

//}

//num:number

//}

复制代码

keyof T 结果是一组key的联合,下面原始的语法也是可行的

type Keys = "option1" | "option2";

type Flags = { [K in Keys]: boolean };

复制代码

你已经发现。映射类型如同JavaScript中的 for(let K in T) 。以下是官方说明

它的语法与索引签名的语法类型,内部使用了 for .. in。 具有三个部分:

类型变量 K,它会依次绑定到每个属性。

字符串字面量联合的 Keys,它包含了要迭代的属性名的集合。

属性的结果类型。

我们可以对 T[K] 做一些处理。

const someType = {

obj:{

one:1

},

num:2

}

//extends 类似于三目运算符

type getType1= {

[K in keyof T]: T[K] extends object ? 1 : 0

}

//object类型转换为字面量1,其他类型为0

type instance1 = getType1//{obj: 1;num: 0;}

复制代码

extends后面会提及,此处可以简单作为三目表达式。

泛型函数与递归

type或者interface,可以看作一个函数,它可以在{}内部调用自身。

const a {

a:'1',

b:'2',

c:{

d:5

}

} as const

type t = { [ K in typeof T]:T[K] extends object ? t : T[K] }

type forA = t //"1" | "2" | 5

复制代码

如果没有泛型参数,它也是泛型函数,也可以调用自身

//这并不报错

interface Map {

[key: string]: Map;

}

复制代码

如果没有{},则不可以调用自身

//Add是把const类型相加的泛型函数

//报错:类型别名“F”循环引用自身。ts(2456)

type F = T extends 10 ? F> : 0

复制代码

conditional Type:T extends U ? X : Y

extends 关键字

首先说明,typescript多处使用 extends 关键字,但它们的作用不尽相同。

//js中的类继承,与ts无关

class A extends B{}

//接口继承

interface Shape {

color: string;

}

interface Square extends Shape {

sideLength: number;

}

//泛型约束

//泛型参数T必须有用length键且类型为number

type getType1= {

[K in keyof T]: T[K]

}

//约束K必须包括一个或以上T的键值

type Pick = {

[P in K]: T[P];

}

//conditional type

type F = T extends object ? 0 : 1

复制代码

typescript中的extends三种场景,

泛型约束,在你输入被约束的泛型参数时,强迫输入值与extends的运算为true

conditional type ,它的运算可真可假 ,true的结果返回X,false返回Y

接口继承,如果interface A extends B{} , 那么A extends B 是一定为真的

以我的理解,它们含义上是一脉继承的。

extends运算

上面说extends的含义上有关联,但是实际conditional type 和 泛型约束在边缘情况下存在差别。

泛型约束

泛型约束的extends 结果要么是true 要么是 false,这个是明确的,它决定编译器的报错与否。

假设 type T ,如A或B有一边是联合类型时,它遵循着一个规则,A必须是B子集

具体而言就是,A的每个元素extends B都要为真。

type B = "1" | "2"

type T= {

[key in A] :0

}

T // { "1":0 }

T //{"1":0,"2":0}

T//报错 不能将类型“"3"”分配给类型“"2" | "1"”。ts(2344)

//相当于

//("1" extends B)&("2" extends B)&("3" extends B)

复制代码

conditional type

distributive conditional types

conditional types中,如果T是 naked type那么 conditional types就被称为分配条件类型(distributive conditional types)。

naked type,然而Typescript并没有说明啥是naked type, 我们大致可以认为就是这个type没有被包裹在其他的复合结构里,如 array , record , function等。如我们可以通过将T包裹为[T]来破坏naked type

type F = T extends U ? X : Y

type union_type = A | B | C

type a = F

//那么a的结果为 A extends U ? X :Y | B extends U ? X :Y | C extends U ? X : Y

复制代码

有一点类似泛型约束的分配运算

最后 我们再看看文章开头的答案

type t = {

[K in keyof T]:T extends object

? t

: T[K]

}[keyof T]

复制代码

已经可以分析清楚了~

刚刚入门typescript,只是凭借实践实例得出自己的理解,有误望指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

latex 图片大小_用LaTeX写作业——插入图片(二)

方法 subfigure可以横向排列一组图片,会自动编号abcd。在一个 subfigure内使用minipage插入图片,通过控制图片大小实现换行效果 # 效果 代码usepackage{subfigure} %所需宏包 usepackage{graphicx}begin{figure}[htbp] centersubfigure[标题…

python中单例模式是什么_python中的单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。比如,某个服务器程序的配置信息存放在一个文件中…

rpm包安装mysql配置文件目录_CentOS6.5系统下RPM包安装MySQL5.6

1.新开的云服务器,需要检测系统是否自带安装mysqlyum list installed | grep mysql2.如果发现有系统自带mysql,果断这么干yum -y remove mysql-libs.x86_643.随便在你存放文件的目录下执行,这里解释一下,由于这个mysql的yum源服务…

单链表的代码python_python版本单链表实现代码

今天看了一下数据结构的书,发现其实数据结构没有几种,线性表,数组,字符串,队列和栈,等等,其实是一回事,然后就是树结构,图结构。数据结构的理论并不难,主要是…

python csv文件复制时的编码问题_使用python读取CSV文件时的编码问题

尝试使用python读取CSV文件时遇到障碍。更新:如果只想跳过字符或错误,可以打开文件,如下所示:with open(os.path.join(directory, file), r, encoding"utf-8", errors"ignore") as data_file:到目前为止&…

zabbix mysql脚本_zabbix监控mysql脚本

vim /usr/local/scripts/mysql_status.sh#!/bin/bash#Desc:zabbix 监控 MySQL 状态#Date:2020-09-05#by:Luojq#主机HOST"localhost"#用户USER"root"#密码PASSWORD"123456"#端口PORT"3306"#MySQL连接…

java rsa算法_求RSA算法JAVA实现源代码(带界面的)

展开全部import javax.crypto.Cipher;import java.security.*;import java.security.spec.RSAPublicKeySpec;import java.security.spec.RSAPrivateKeySpec;import java.security.spec.InvalidKeySpecException;import java.security.interfaces.RSAPrivateKey;import java.sec…

redis事务java_java 使用RedisTemplate实现Redis事务

关系型数据库事务的作用是保证并发访问下数据的一致性,Redis事务有些不同,由于Redis是单线程的处理来自client的指令,所以Redis所有命令的执行都是原子性的,举一个简单的例子,单个Redis服务器下,并发地执行…

java string值传递_String是值传递还是引用传递

string中的坑最近看到一道关于string的面试题,差点让我以为string是值传递,就是下面这个例子,体验下:public class demo{public static void main(string[] args) {demo d new demo();string str "bea";d.change(str)…

java切换jdk版本_切换JDK版本quick

最近遇到一个小问题,同时做两个项目,jdk版本一个是5,一个是6,我也去网上找了找方法,但是感觉不是特别好用,最后自己通过一些环境变量设置的技巧和一些批处理命令来使得这件事情只需要双击,输入一…

java读取excel数据的方法是_java怎么读取excel文件里的数据

展开全部下面是一个简单的读取例子,如果报“java.io.IOException: Invalid header signature; read 4503608217567241, expected -2226271756974174256”之类的异常请用Excel打开(如果能打的开的话)62616964757a686964616fe58685e5aeb931333361323639然后另存为一下…

Linux下导出MySQL为SQL文件_MySQL导入导出.sql文件步骤

MySQL导入导出.sql文件步骤如下:一.MySQL的命令行模式的设置:桌面->我的电脑->属性->环境变量->新建->PATH“;path\mysql\bin;”其中path为MySQL的安装路径。二.简单的介绍一下命令行进入MySQL的方法:1.C:\>mys…

python sort 多级排序_Python使用sort和class实现的多级排序功能示例

本文实例讲述了Python使用sort和class实现的多级排序功能。分享给大家供大家参考,具体如下:# -*- coding:utf-8 -*-import randomclass Temp:def __init__(self, a, b, c):self.a aself.b bself.c cdef __str__(self):return ( ([a: %d b: %d c: %d] …

the java home_the java_home environment variable is not defined correctly

在启动tomcat中的startup.bat时,总是报以下错误the java_home environment variable is not defined correctlyThis environment variable is needed to run this programNB: java_home should point to a jdk not a jre环境变量的路径没有问题,把jdk重装…

java中添加背景_java中如何增加背景图片

我的程序代码如下,试了加背景的方法虽然程序没有错误,但是背景还是显示不出来,按钮的setsize好像也不起作用,希望高人能助一臂之力,小女子先写过各位了:、、、、importjava.awt....我的程序代码如下&#x…

java存钱_用Java编写银行存钱取钱

const readline require(readline-sync)//引用readline-synclet s 2;//错误的次数for (let i 0; i < 3; i) {console.log(请输入名&#xff1a;(由英文组成));let user readline.question();console.log(请输入密码&#xff1a;(由数字组成));let password readline.qu…

我的世界java服务器刷_一个教程, 叫你如何在服务器刷op

教 你 如 何 在 服 务 器 内 刷 取op~&#xff01;首先打开JAVA文件夹找到bin\client 里面的Xusage然后打开然后会得到这个内容-Xmixed mixed mode execution (default)-Xint interpreted mode execution only-Xbootclasspath:set search path for boots…

mysql 小雨_Mysql数据库

Mysql服务配置安装mysqld服务&#xff1a;yum groupinstall ‘mysql database server’yum –y install mysql-server php-mysql服务名&#xff1a; mysqld默认的数据库存放在&#xff1a; /var/lib/mysql下启动服务&#xff1a; service mysqld restart可以直接登陆&#xff1…

java eav_动态自定义字段属性–Magento的EAV模型 | 学步园

EAV &#xff1a; Entity - Attribute - Value 的缩写&#xff0c;是数据库模型的一种&#xff0c;使用eav建模的好处是可以动态为数据模型增加或移除属性。1. 问题提出:假设需要定义一个实体Customer的信息&#xff0c;通常我们只要定义一个表为customer&#xff0c;并定义相应…

java 对象视图框架_Stripes视图框架Java对象属性验证和prototype.js Ajax的测试

Stripes视图框架Java对象属性验证&#xff0c;它允许对字段设置是否必须填写&#xff0c;对数字大小进行限制等。我用prototype.js Ajax 将验证后的数据及时地展示出来&#xff0c;下面来看程序。1、编写User实体类此用户共三个属性&#xff1a; name、email、age.package com.…