TS是包含了JS的内容的,或者说TS是在JS上做的改进
因此更适合大型项目的开发
JS在诞生时的定位是浏览器脚本语言,用于在网页中浅入一些简单的逻辑,而且代码量很少
现如今的JS应用场景比以前丰富太多,代码量也比以前大很多。而当时JS就没有考虑倒如今的应用场景和代码量,逐渐出现了很多缺点;
不清不楚的数据类型
let s = "hello"
s() // 报错:TypeError: s is not a function
在代码量少的时候可以很清晰的看见这是一个字符串不是一个方法,会报错 而当代码量多了后,真的出现调用这种情况时如何定位?
有漏洞的逻辑
const str = Date.now() % 2 ? '奇数' : '偶数'
if(str!=='奇数'){
alert('hello')
}else if (str==='偶数'){
alert('world')
}
判断是否是偶数,其实else if内的代码块永远不会被执行 当命中第一个if时,else if就不会被执行了 那么,在这时 JS 并不会给出任何的逻辑上的提示
访问不存在的属性(普遍是null)
const obj = { width: 10, height: 15};
const area = obj.width * obj.heighth;
在JS里,如果出现调用一个不存在的属性,一样不会给出任何的提示 哪怕出现的是一个错误的、不可计算的结果
低级的拼写错误
const message = 'hello, world';
message.toUperCase();// 正确的方法名称:.toUpperCase();
如果出现拼写错误,导致无法调用函数,JS一样不会给出任何提示
TS能够解决上述JS出现的问题,这源于TS使用了【静态代码检查】功能
后期代码的维护中TS却远胜于JS
**tsc
命令在使用 tsc 命令前,还需要安装ts环境
npm i typescript -g
tsc ts文件名
使用后,会相同文件夹下编译生成一个js文件
var a = 10;
console.log("数字是:"+a)
var a = 10;
console.log("数字是:" + a);
命令 | 说明 |
---|---|
tsc --init | 生成自动化配置文件 |
tsc --watch [ts文件] | 监视某一个ts文件,当ts文件发生任何改动,都会实时生成JS |
tyc --noEmitOnError – watch | 当编译出错时不生成 .js 文件(不推荐,更建议修改tsconfig.json中的noEmitOnError配置) |
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "noUncheckedSideEffectImports": true, /* Check side effect imports. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
let a: string
let b: number
let c: boolean
a = 'hello'
b = 100
c = true
console.log(a,b,c)// hello 100 true
限定函数的参数类型
function count(x:number,y:number){
return x+y
}
let result = count(1,2)
console.log(result)// 3
限定函数的返回类型
function count(x:number,y:number):string{
return x+y+"数量"
}
let result = count(1,2)
console.log(result)
字面量类型
let a: string
let b: 'test'
a = 'hello'
b = 'name'
当类型限定为一个字面量常量时,那么该变量只会是这个字面量常量值,不可发生改变
TS
会根据我们的代码,进行类型推导,例如下面代码中的变量d
,只能存储数字
let d = -99
d = false // 报错
请注意,类型推断不是万能的,面对复杂类型时推断容易出问题,所以尽量还是明确的编写类型声明
let d: number = -99
d = false // 报错
关键字 | 说明 |
---|---|
string | 字符串 |
number | 数量 |
boolean | 布尔 |
null | 空 |
undefined | 未定义 |
bigint | 大整形 |
symbol | 标记 |
object | 对象 |
object类型中,还包含:
Array
、Function
、Date
等
新增了下述类型
关键字 | 说明 |
---|---|
any | 任意类型 |
unknown | 未知 |
never | 不存在值的类型 |
void | 没有类型 |
tuple | 数组 |
enum | 枚举 |
type | 类型 |
interface | 接口 |
在JS中的内置构造函数:
Number
,String
,Boolean
,它们会用于创建对应的包装对象,在日程开发时很少使用,在TS中也是同理,所以TS中进行类型声明时,通常都是用小写的number
、string
、boolean
let a: string = 'a'; // TS更加推荐这种
let b = new String('b');// String是一个包装类
let c: String = 'c';// 使用的包装类,不推荐;更加占用资源
number
、string
、boolean
在JS中是简单的数据类型,它们在内存中占用空间少,处理速度快
Number
,String
,Boolean
是复杂类型,在内存中占用更多的空间
any
的含义是:任意类型,一旦将变量类型限制为any
,那就意味着放弃了对改变了的类型检查let a: any
a = 100
a = "你好"
a = false
// 如果不加任何的类型限定,默认就是 【any】类型
let b
b = 100
b = "你好"
b = false
注意:
any
类型的变量,可以复制给任意类型的变量
let a: any
a = false
let c: string
c = a
unknown
的含义是:未知类型可以将unknown理解为一个类型安全的any
,适用于:不确定数据的具体类型
let a: unknown
a = 100
a = "你好"
a = false
let c: string
c = a // 警告,不能将类型“unknwon”分配给类型“string”
不过也可以赋值,需要进行判断或者断言
判断
let a: unknown
a = 100
a = false
a = "你好"
let c: string
// 判断
if(typeof a === 'string'){
c = a
}
断言
let a: unknown
a = 100
a = false
a = "你好"
let c: string
c = a as string // 断言
c = <string> a // 断言
调用函数时,也和any
存在不同
let str1: string
str1 = 'hello'
str1.toUpperCase() // 无警告
let str2: any
str2 = 'hello'
str2.toUpperCase() // 无警告
let str3: unknown
str3 = 'hello'
str3.toUpperCase() // 警告:“str3”的类型为“未知”
never
的含义是:任何值都不是(不能有值)几乎不用never
去直接限制变量,因为没有意义:
let a: never
a = 1
a = true
a = undefined
a = null
never
一般是TypeScript
主动推断出来的
let a: string
a = 'hello'
if(typeof a==='string'){
console.log(a.toLowerCase())
}else{
// 这里推断出来时 never,因为没有任何一个值会符合此处的逻辑
console.log(a)
}
never
也可用于限制函数的返回值
function throwError(str: string):never{
throw new Error("程序异常退出:"+str)
}
never作为返回值,一般来说,就是在这个方法无法正常结束的时候才符合标准
void
通常用于函数返回值声明,含义:【函数不返回任何值,调用者也不应该依赖其返回值进行任何操作】
function logMessage(msg: string):void{
console.log(msg)
}
logMessage('hello');
编码者没有编写
return
去制定函数的返回值,所以logMessage
函数时没有显示返回值的,但会有一个隐式返回值,就是undefined
;即:虽然函数返回类型为void
,但也可以接收undefined
,简单点来说:undefined 是 void 可以接收的一种 “空”
以下三种方式声明是没有问题的
function logMessage1(msg: string):void{
console.log(msg)
}
function logMessage2(msg: string):void{
console.log(msg)
return
}
function logMessage3(msg: string):void{
console.log(msg)
return undefined
}
void
函数返回值无法进行任何操作
////////////////////////////////void///////////////////////////////////
function logMessage4(msg: string):void{
console.log(msg)
}
let s1 = logMessage4("hello")
if(s1){ // 警告:无法测试 "void" 类型的表达式的真实性
console.log("logMessage4");
}
////////////////////////////////undefined///////////////////////////////////
function logMessage5(msg: string):undefined{
console.log(msg)
}
let s = logMessage5("hello")
if(s){
console.log("logMessage5");
}
理解void与undefined
void
是一个广泛的概念,用来表达“空”,而undefined
则是这种“空”的具体实现之一undefined
是void
能接收的“空”状态的一种具体形式void
包含undefined
,但void
表达的语义超越了单纯的undefined
,它是一种意图上的约定,而不仅仅是特定值的限制总结:
若函数返回类型是void
那么:
undefined
的undefined
值关于
object
和Object
,实际开发中使用的相对较少,因为范围太大了
object
的含义是:所有非原始数据类型 都可以存储:对象、函数等
let a:object
a = {}
a={name:"张三"}
a=[1,2,3,4,5]
a=function(){}
a=new String("12")
class Person{}
a = new Person()
/////////////// 无法使用 ////////////////
a = 1
a = false
a = "hello"
a = null
a = undefined
Object
方法的类型undefined
和null
的任何值let a:Object
a = {}
a={name:"张三"}
a=[1,2,3,4,5]
a=function(){}
a=new String("12")
class Person{}
a = new Person()
a = 1
a = false
a = "hello"
/////////////// 无法使用 ////////////////
a = null
a = undefined
通用模式:
let person1: {name: string,age:number}
person1 = {name: "zhangsan",age: 18}
////////// 两种:带或不带 ? ///////////////
let person2: {name: string,age?:number}
person2 = {name: "zhangsan"}
索引签名:
允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的,常用于:描述类型不确定的属性(具有动态属性的对象)
let person3: {
name: string,
age?: number,
// 索引签名
[key:string]:any
}
person3 = {name:"zhangsan",age:18,address:"湖南"}
let count: (a:number,b:number) => string // 规定了函数的数据类型,参数类型是number,返回值类型是string类型
count = (x,y)=>{
return x+y+"字符串"
}
=>
在函数类型声明时表示函数类型,描述其参数类型和返回类型=>
是一种定义函数的语法,是具体的函数实现 let arr1: string[] // 规定了类型:数组内的每一项必须是字符串
let arr2: Array<string>
arr1 = ["a","b","c"]
arr2 = ['hello','world']
上述代码中的Array<string>
属于泛型
元组(Tuple)是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。
元组用于精确描述一组值的类型,?
表示可选元素
let arr1: [string,number]
let arr2: [number,boolean?]
let arr3: [number,...string[]]
arr1 = ["hello",1]
arr2 = [100,false]
arr2 = [20]
arr3 = [100,"hello","world"]
arr3 = [100]
枚举(enum)可以定义一组命名常量,它能增强代码的可读性,也让代码更好维护
如下代码的功能是:根据调用walk
时传入的不同参数,执行不同的逻辑。
存在的问题是调用walk
时传参时没有任何提示,编码者很容易写错字符串内容,并且用于判断逻辑的up
、down
、left
、right
时连续且相关的一组值,那么这个时候**使用枚举(enum)**就非常的适用
function walk(str:string){
if(str === 'up'){
console.log("上");
}else if(str === 'down'){
console.log("下");
}else if(str === 'right'){
console.log("右");
}else if(str === 'left'){
console.log("左");
}else{
console.log("未知");
}
}
walk("up")
walk("down")
walk("right")
walk("left")
数字枚举一种最常见的枚举类型,其成员的值会自动递增,且数字枚举还具备反向映射的特点
enum Direction{
UP,
DOWN,
LEFT,
RIGHT
}
console.log(Direction)
/*
{
"0": "UP",
"1": "DOWN",
"2": "LEFT",
"3": "RIGHT",
"UP": 0,
"DOWN": 1,
"LEFT": 2,
"RIGHT": 3
}
*/
console.log(Direction.UP);// 0
console.log(Direction[0]);// UP
// 报错代码:
Direction.UP = 1 // 枚举中的值是只读的
使用数字枚举完成walk
函数的逻辑,可以发现:代码更加直观易读,而且类型安全,同时更加易于维护
function walk(data:Direction){
if(data === Direction.UP){
console.log("上");
}else if(data === Direction.DOWN){
console.log("下");
}else if(data === Direction.RIGHT){
console.log("右");
}else if(data === Direction.LEFT){
console.log("左");
}else{
console.log("未知");
}
}
walk(Direction.UP)
walk(Direction.DOWN)
walk(Direction.RIGHT)
walk(Direction.LEFT)
枚举成员的值是字符串
enum Direction1{
UP1 = "UP",
DOWN1 = "DOWN",
LEFT1 = "LEFT",
RIGHT1 = "RIGHT"
}
/*
{
"UP": "UP",
"DOWN": "DOWN",
"LEFT": "LEFT",
"RIGHT": "RIGHT"
}
*/
console.log(Direction1)
let dir: Direction1 = Direction1.UP1
console.log(dir) // 输出:“UP”
官方描述:常量枚举是一种特殊枚举类型,它使用
const
关键字定义,在编译时会被内联,避免生成一些额外的代码。
所谓 “内联”,其实就是 TypeScript 在编译时,会将枚举成员引用替换为它们的实际值,而不是生成额外的枚举对象。这可以减少生成的JS代码量,并提高运行时性能
type
可以为任意类型创建别名,让代码更简介,可读性更强,同时能更方便地进行类型复用和扩展。
类型别名使用
type
关键字定义,type
后跟类型名称,例如下面代码中的num
是类型别名
type num = number
let price: num
price = 100
联合类型是一种高级类型,它表示一个值可以是几种不同的类型之一
type Area = {
height: number;
width: number;
}
type Address = {
num: number;
cell: number;
room: string;
}
// 代表test类型,只能是Area类型或者Address类型其中一种
type test = Area | Address
// 代表House类型,必须包含Area和Address两种类型
type House = Area & Address
let x: House = {
height: 100,
width: 20,
num: 1,
cell: 123,
room: "008"
}
特殊点:
使用类型声明限制函数返回值为 void
时,TypeScript
并不会严格要求函数返回空
type LogFunc = () => void
const f1:LogFunc = function(){
return 66 // ?void不是只能接受返回undefined吗,怎么这里返回number类型不报错
}
WHY?为什么可以这样? 其实是为了确保
Array.prototype.forEach
方法其回调的返回类型是void
保证能够正常运行
class Person{
name: string;
age: number;
// 基本构造函数
constructor(name: string,age: number){
this.name = name
this.age = age
}
speak(){
console.log(`我叫:${this.name},今年${this.age}岁`);
}
}
class Student extends Person{
grade: string;
constructor(name: string,age: number,grade: string){
super(name,age) // 继承父类,必须使用super()方法
this.grade = grade
}
study(){
console.log(`${this.name} 正在努力学习中...`);
}
}
const s = new Student("张三",15,"一年级")
s.speak() // 我叫:张三,今年15岁
s.study() // 张三 正在努力学习中..
console.log(s);
/**
{
"name": "张三",
"age": 15,
"grade": "一年级"
}
*/
console.log(s.grade);// 一年级
修饰符 | 含义 | 具体规则 |
---|---|---|
public | 公开的 | 可以被:类内部、子类、类外部访问 |
protected | 受保护的 | 可以被:类内部、子类访问 |
private | 私有的 | 可以被:类内部访问 |
readonly | 只读属性 | 属性无法修改 |
class Person{
public name: string;
age: number;
// 基本构造函数
constructor(name: string,age: number){
this.name = name
this.age = age
}
speak(){
console.log(`我叫:${this.name},今年${this.age}岁`);
}
}
const p1 = new Person("张三",18)
// 类的外部,可以访问public修饰的属性
console.log(p1.name)
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
////////////// 简写后 /////////////
class Person1 {
constructor(
public name: string,
public age: number
) {
}
}
class Person {
constructor(protected name: string,protected age: number) {}
protected getDetails(){
return `我叫:${this.name},年龄是:${this.age}`
}
introduce(){
console.log(this.getDetails);
}
}
const p1 = new Person("tom",18)
p1.introduce()
// 无法访问,因为这些属性都是受保护的(protected)
// p1.name
// p1.age
// p1.getDetails
子类是否可以调用?
class Person {
constructor(protected name: string,protected age: number) {}
protected getDetails(){
return `我叫:${this.name},年龄是:${this.age}`
}
introduce(){
console.log(this.getDetails);
}
}
class Student extends Person{
study(){
this.introduce()
console.log(`${this.name}正在努力学习`);
}
}
const s1 = new Student("cat",10)
s1.study()
回答是不可以
class Person {
constructor(
protected name: string,
public age: number,
private IDCard: string
) {}
private getPrivateInfo(){
return `身份证号码为:${this.IDCard}`
}
getInfo(){
return `我叫:${this.name},今年刚满${this.name}岁`
}
getFullInfo(){
return this.getInfo+","+this.getPrivateInfo()
}
}
const p1 = new Person("tom",18,"1231231233441")
// p1.name // 无法访问 protected
// p1.age // 可访问
// p1.IDCard // 无法访问 private
console.log(p1.getInfo());
console.log(p1.getFullInfo());
// p1.getPrivateInfo(); // 无法使用 private
class Person {
constructor(
protected readonly name: string,
public readonly age: number,
private IDCard: string
) {}
}
概述:
简记:
abstract class Animal{
constructor(
public name:string,
public age:number,
public type: string
){}
abstract shout(): string
do(){
console.log(`一只叫做${this.name}的${this.type}开始发出:${this.shout()}的声音`);
}
}
class Cat extends Animal{
constructor(
name:string,
age:number,
){ super(name,age,"猫") }
shout(): string {
return "喵~~";
}
}
const c1 = new Cat("蛋黄",3)
c1.do()
什么时候使用抽象类?
interface
是一种定义结构的方式,主要作用是为:类、对象、函数等规定一种规范,这样可以确保代码的一致性和类型安全
但要注意interface
只能定义格式,不能包含任何实现!
interface IPerson{
name: string,
age: number,
number(n:number):void
}
class Person implements IPerson{
constructor(
public name: string,
public age: number,
){}
number(n: number): void {
console.log(`测试:${n}`);
}
}
const p = new Person("张三",18)
p.number(12)
同时,在TS中接口还可以当作对象使用
const p1: IPerson = {
name: "张三",
age: 18,
number: function (n: number): void {
console.log(`测试:${n}`);
}
}
与其他语言不一样,TS里,接口名是可以重复的
官方叫做接口合并,意思是,相同接口名的接口都必须实现对应的属性
interface IPerson{
name: string,
age: number,
number(n:number):void
}
interface IPerson{
grender: string
}
什么时候使用接口:
interface
和 type
都可以用于定义对象结构,两者在许多场景中是可以互换的。interface
:更专注于定义对象和类的结构,支持继承、合并type
:可以定义类型别名、联合类型、交叉类型,但不支持继承和自动合并泛型允许我们在定义函数、类或接口时,使用类型参数来表示未指定的类型,这些参数在具体使用时,才被制定具体的类型,泛型能让同一段代码适用于多种类型,同时仍然保持类型的安全性
const f = <T,U>(a:T,b:U)=>{
console.log(a,b);
}
// 使用泛型,指定传入方法内的类型
f<number,string>(1,"zhangsan")
f<number,number>(1,22)
泛型类:
class Person<T>{
constructor(
public name: string,
public age: number,
public extraInfo: T
){}
speak(){
console.log(`我叫:${this.name}今年${this.age}岁了`);
console.log(this.extraInfo);
}
}
const p1 = new Person<number>("tom",30,100)
type JobInfo = {
title: string,
company: string,
}
const p2 = new Person<JobInfo>("tom",30,{title:"程序员",company:"华为"})
在实例化对象时,定义了什么泛型类,就必须传入对应的类型数据
类型声明文件时 TS 中的一种特殊文件,通常以.d.ts
作为扩展名。
它的主要作用是为现有的JS代码提供类型信息,使得TS能够在使用这些JS库或模块时进行类型检查和提示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--type需要更改为 module-->
<script type="module" src="./index.js"></script>
</body>
</html>
import {add,mul} from './demo.js'
console.log(add(1,2));
console.log(mul(1,2));
export function add(a,b){
return a+b;
}
export function mul(a,b){
return a*b;
}
declare function add(a:number,b:number):number
declare function mul(a:number,b:number):number
export{add,mul};