如何运行ts文件以及如何把ts文件转化为js文件
JavaScript对应的ts类型
ts的其他类型
断言、非空断言 、?? 、!! 和类型缩小、可选链和字面量推理
函数的使用
类的使用
接口的使用
泛型的使用
类型得查找
10.tsconfig.json文件
11.注意
1.如何运行ts文件以及如何把ts文件转化为js文件
1)如何把ts文件转化为js文件
a.安装包typescript
b.终端执行tsc 文件名.ts
npm install -g typescript
2).如何运行ts文件
建立package包 npm init -y
安装包@types/node ts-node
修改package文件的test
运行test命令
npm init -y
npm i @types/node --save-dev
npm i ts-node -g
"scripts": {
"test": "ts-node index.ts"
},
最后node终端执行node test
2.JavaScript对应的ts类型
在Javascript中 基础数据类型有Number、String、Boolean、Null、Undefined、Symbol,复杂数据类型有Array和Object
// number类型
let number1:number
number1=1
// string类型
let string1:string
string1='string'
// boolean类型
let boolean1:boolean
boolean1=false
// null类型
let null1:null
null1=null
// undefined类型
let undefinded1:undefined
undefinded1=undefined
// symbol类型
let symbol1:symbol
// Symbol的S是大写
symbol1=Symbol(1)
// 数组类型和元组类型
// 数组有两种写法 一般用第一种 第二种在jsx里面会有冲突
let arr:string[]
arr=['1','2']
// 不是Array[string] 而是Array<string>
let arr1:Array<string>
arr1=['1','2']
// 元组类型 和数组类型得区别是元组类型里面的类型具体到索引并且可以不同
let tuple1:[string,number]
tuple1=['1',1]
// object类型
let obj:object
// obj.obj1=1 不能赋值和取值
obj={obj1:1,obj2:2}
3.ts的其他类型
ts还有any、nerver、unknow、void、可选类型、字面量类型、联合类型、交叉类型和枚举类型
1)any、nerver、unknow、void、可选类型、字面量类型、联合类型、交叉类型
// any类型
let any:any
any=1
// unknown类型
let unknow:unknown
unknow=1
// nerver类型
// 不能直接赋值nerver
// let nerver:nerver
function name1(params:string):string {
switch(typeof params){
case 'string':
return 'string';
default:
let check:never=params
return check
}
}
// void类型
// 不是volid 是void
function fn2():void{
console.log('volid');
}
// 字面量类型
let ab:'jh'
ab='jh'
// 联合类型
let combile:'ab'|'a'
combile='a'
// 交叉类型
let combile1:'ab'&'a'
//可选类型
interface obj {
name?:string,
nameq:number
}
let obj1:obj={
nameq:1,
}
2)枚举类型(就是有默认值的联合类型)
// 枚举类型 基本使用
enum Drection {
right,
bottom,
}
function DrectionFn(type:Drection){
switch (type){
case Drection.right:
return 'right'
case Drection.bottom:
return 'bottom'
default:
return 'notFund'
}
}
// 枚举类型是有默认值的 如果不给默认值 默认值就是索引值 即第一个值是0 后面累加1
console.log(DrectionFn(0));
// 当第一个值赋值是数字的时候 后一个的默认值就是前一个的加1
enum Drection2 {
right=3,
bottom,
}
function Drection2Fn(type:Drection2){
switch (type){
case Drection2.right:
return 'right'
case Drection2.bottom:
return 'bottom'
default:
return 'notFund'
}
}
// 会和bottom匹配 因为前一个是3 这个默认就是4
console.log(Drection2Fn(4));
// 如果前一个不是数字 而是字符串 后一个必须给默认值 否则无法运行代码
// enum Drection3 {
// right='right',
// bottom,
// }
enum Drection3 {
right='right',
bottom='bottom',
}
function Drection3Fn(type:Drection3){
switch (type){
case Drection3.right:
return 'right'
case Drection3.bottom:
return 'bottom'
default:
return 'notFund'
}
}
// 传入的必须是Drection3类型 数字除外 不然无法运行
// console.log(Drection3Fn('right'));
console.log(Drection3Fn(Drection3.right));
4.断言、非空断言 、?? 、!! 和类型缩小、类型保护、可选链和字面量推理
字面量推理就是根据上下文推理出变量的类型,从而不需要写类型
可选链就是它的作用是当对象的属性不存在时,会短路,直接返回undefined,如果存在,那么才会继续执行
类型缩小就是可以缩小比声明时更小的类型,这个过程称之为 缩小(通过typeof等判断)
如果是等值 如typeof padding === "number 可以称之为 类型保护
// 断言 (只能转换成具体或更不具体的 不能强制转换 而且断言是变量或dom或函数然后as 类型)
let abss:unknown
abss='a' as string
// ??和|| 是有区别的 区别在于0和false
// || 如果前面不是null undefined 0 false就返回 否则返回后面部分
// ?? 如果前面不是null undefined就返回 否则返回后面部分
// && 如果前面是null undefined 0 false就返回 否则返回后面部分
console.log(1??2);//1
console.log(1||2);//1
console.log(1&&2);//2
console.log(0??2);//0
console.log(0||2);//2
console.log(0&&2);//0
// 非空断言 我们传入的一定是有值的 所以可以用非空断言
//me如果不给any类型会说暗指的any类型在ts文件内报错 所以必须添加类型
function basss(me?:any):number{
return me.length
}
// 数字类型是没有长度的
console.log(basss('989'));
// 可选链
let obj4={
num:{
num1:3
}
}
// 如果obj4的num里面没有num1 返回undefined 如果有继续往下取num1
console.log(obj4.num?.num1);
5.函数的使用
// 函数(内容包括默认参数 可选参数(其实是一个类型和undefined的组合)参数是对象类型 剩余参数 匿名函数的类型 函数重载)
// 函数的定义 两种方式定义 type和interface 一般type定义函数 interface定义对象 interface定义是可以重复的
type fn8=()=>void
function fn12(fn:fn8){
console.log(22);
}
const fn13:fn8=()=>{
console.log(22);
}
interface fn14{
():void
}
const f21:fn14=()=>{
console.log(22);
}
function fn3(num=1,num2?:string){
console.log(num);
}
fn3(2)
// 函数 对象参数 不是这样写的
// function fn4({a:string,b:number}){
// console.log(a);
// }
function fn4(ab:{a:string,b:number}){
console.log(ab.a);
}
let obj5={a:'1',b:1}
fn4(obj5);
// 函数剩余参数
fn4({...obj5});
// 匿名函数:就是没有名字的函数 匿名函数的参数会被自己推导
(function (str){
console.log('我是匿名函数');
})('匿名函数')
// 函数的重载 当调用的时候先会去匹配函数重载类型对不对 然后再执行函数的实现 fsn5的实现体写在下面
// 函数重载
function fsn5(num:string,num2:number):void;
function fsn5(num:number,num2:number):void;
// 函数实现
function fsn5(num:any,num2):void{
console.log(333);
}
fsn5('12',1)
6.类的使用
// 类的学习 继承 public prective protect readonly四种类型 get 和set 抽象类
// 继承
class Person {
static num=3
private age1:number=2
protected age3:number=3
readonly age4:number=3
age:number
name:string
get (){
return this.age1
}
constructor(x:number,y:string){
this.age=x
this.name=y
}
}
class Student extends Person {
student:boolean
get3 (){
// private是不能访问的
// this.age1
// this.age3
}
constructor(x:boolean,y:number,z:string){
super(y,z)
this.student=x
}
}
const xiaoHong=new Student(true,1,'xiaohong')
const xiaoHong2=new Person(1,'xiaohong')
// 当打印的时候 private的age1都是可以打印出来的
console.log(xiaoHong);
console.log(xiaoHong2);
// 但是这样去取的时候 是取不到的 会报错
// console.log(xiaoHong.age1);
// console.log(xiaoHong2.age1);
// 如果要取 只能通过set get
console.log(xiaoHong.get());
console.log(xiaoHong2.get());
console.log(xiaoHong.age4);
console.log(xiaoHong2.age4);
console.log(Person.num);
// 结论 private在子类和类的实现中都是可以打印出来 但是不能直接获取和修改 但是可以通过方法获得
// protected和private的区别 protected在子类是可以用this访问的
// readonly 只能读取 不能修改 子类和当前类实现能访问 static可以通过对象访问 但是不能通过实现访问
// 抽象类
abstract class Ab {
abstract num:number
}
// 抽象类变成实体类 是通过继承 而不是ts类型方式 下面写法错误
// class Abc:Ab{
// }
// 记住类里面的赋值不是:而是等于号赋值
class Abc extends Ab{
num=1
}
let Abs=new Abc()
7.接口的使用
// 接口:定义对象的时候 实现 索引 只读 可选 定义函数 继承
// 接口定义对象 只读 可选
interface obj3 {
num:number
// 可选
num1?:number
// 只读 只能获取 不能赋值 赋值会编译报错
readonly num2:number
}
// 实现
let obnj:obj3={
num:2,
// num1:3,
num2:3
}
// 索引类型
// 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number 来索引时,JavaScript 会将它转换成 string 然后再去索引对象。
interface obj33{
[index:number]:string
[str:string]:string
}
// number索引 一般用在数组里
interface obj333{
[index:number]:number
}
let bj:obj333=[3,8,9]
interface obj3339{
[index:string]:number
}
let ou:obj3339={
'jkh':11,
}
// 接口在函数的使用
interface ij{
():void
}
const Af:ij=()=>{
console.log(78);
}
Af()
8.泛型的使用
// 泛型的使用 如何使用 调用 传入多个类型 泛型在接口的应用 在类的使用 在函数的使用 泛型约束
// 如何使用
// 这就是一个函数加上类型 第一个number是参数类型 第二个number是返回值类型
function generic(num:number):number{
return num
}
// 当使用泛型 当使用泛型的时候 只需在函数名后加<T>即可
function generic2<T>(num:T):T{
return num
}
// 调用的时候有两种方式 第一种通过类型推导
console.log(generic2(2));
// 第二种 传入类型 还是在函数名后面写<T>
console.log(generic2<number>(2));
// 泛型扩展 传入多个类型
function generic3<T,E>(ar1:T,ar2:E):T{
return ar1
}
console.log(generic3(2,'jkh'));
// 泛型在接口的应用 泛型的类型可以给默认值 给默认值后 下面可以只写一个 默认和这里的第一个匹配
interface Foo<T,E=string>{
generic:T,
generic1:E,
}
const genericInterface: Foo<number>={
generic:1,
generic1:'generic1'
}
console.log(genericInterface);
// 泛型在类的使用 这个T和调用传人的参数不是同一个
class genericClass<T>{
// 可以用在这以及规定调用时候传入的类型
generic:T
generic1
// 调用时候的限定
constructor(x:T){
// 对于类 只有带有继承的才能用super 注意上面定义的值必须要有初始化 就是要么赋值默认值 要么就是contructor里面调用
this.generic=x
this.generic1=x
}
}
const genericInstance=new genericClass<number>(2)
console.log(genericInstance);
// 泛型在箭头函数的使用
const genericFunction=<T>(num:T):T=>{return num}
console.log(genericFunction<number>(2));
// 泛型约束 就是通过继承 限制传入类型 不能多继承
interface str1{
string1:string
}
interface num1{
number:number
}
interface numStr extends str1,num1{
}
const numStr1:numStr={
string1:'87',
number:12
}
function bounds<T extends num1>(num:T):T{
return num
}
console.log(bounds<numStr>(numStr1));
9.类型的查找
1)内置类型声明:(是typescript自带,比如Math、Date等内置类型)
2)外部定义类型声明:(在自己库中进行类型声明(编写.d.ts文件),比如axios,通过社区的一个公有库DefinitelyTyped存放类型声明文件 npm使用即可)
该库的GitHub地址:https://github.com/DefinitelyTyped/DefinitelyTyped/
该库查找声明安装方式的地址:https://www.typescriptlang.org/dt/search?search=
3)自己定义类型声明:建立.d.ts文件,声明类型即可 注意ts-node会编译的时候会忽略.d.ts文件,需要在typeScript.json进行配置types,注意types里面文件名不需要尾缀,带尾缀会报ts找不到该文件错误,.d.ts文件的位置是哪里都可以,也不需要引入
// 声明模块
declare module 'lodash' {
export function chunk(arg:string[],num:number):any[];
}
// 声明变量
declare let stru:string
// 声明函数
declare function strua():void
// 声明类
declare class Person{
name:string
constructor(name:string)
}
// 声明命名空间
declare namespace ${}
{
"compilerOptions": {
"types": ["./src/declaration"],
"esModuleInterop": true,
},
}
10.tsconfig.json文件
“ tsc --init ” 初始化tsconfig.json 文件 tsc 文件名.ts 执行后,会自动生成js文件
tsconfig.json是用于配置TypeScript编译时的配置选项:https://www.typescriptlang.org/tsconfig
11.注意:
1)TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension “.ts“
在package.json中删除
"type":"module"
当通过tsc命令或ts-node运行文件时,系统会去读取tsconfig.json文件,我们对于其模块化的指定需写在这个文件内,而不是package文件,在ts配置文件内配置转换成commonjs代码执行"module": "commonjs",转换成es6模块执行,如果是es6就es6执行
2)两个ts文件都在同一个目录下,每个ts 都定义了相同变量就会报错,为什么不同文件下的ts,他们却公用了同一个全局环境?
两个ts文件都在同一个目录下,每个ts 都定义了相同变量就会报错,为什么不同文件下的ts,他们却公用了同一个全局环境?求解
在默认情况下,当你开始在一个新的 TypeScript 文件中写下代码时,它处于全局命名空间中,使用全局变量空间是危险的,因为它会与文件内的代码命名冲突。改成使用文件模块,文件中包含import或者export,就会在当前文件中创建一个本地作用域 这是ts特性之一。防止你写重复的变量名。