Typescript(一) 环境搭建与十二大基础属性针对npm 用户可以安装包依赖
然后再安装tsx 运行
在一个新的文件夹里面新建一个Basic1.ts 文件
constgetTime:()=>void=()=>{
console.log(newDate().toLocaleString());
};
getTime();
const test_number_1:number=100;
const test_number_2:number=100.5;
const test_number_3: bigint =100n;
console.log(test_number_1);// 100
console.log(test_number_2);// 100.5
console.log(test_number_3);// 100n
const test_boolean_1:boolean=true;
console.log(test_boolean_1);// true
const test_boolean_2:boolean=false;
console.log(test_boolean_2);// false
const test_string_1:string="hello world";
console.log(test_string_1);// hello world
const test_null_1:null=null;
console.log(test_null_1);// null
const test_undefined_1:undefined=undefined;
console.log(test_undefined_1);// undefined
const test_array_1:number[]=[1,2,3,4,5];
console.log(test_array_1);// [1, 2, 3, 4, 5]
const test_array_2:string[]=["hello","world"];
console.log(test_array_2);// ["hello", "world"]
// 数组和字符串混用
const test_array_3:(number|string)[]=[100,"hello",200,"world"];
console.log(test_array_3);// [100, "hello", 200, "world"]
// 可以赋值对象、数组、函数等
const obj: object ={};
const arr: object =[1,2,3];
const fn:object=()=>{};
对象类型 object 非常宽泛,只能访问对象共有的方法.比如(valueOf(),equals(),hashCode(),toString(),equals(),hashCode()).
const person: object ={ name:"Alice", age:25};
// ❌ 错误:不能访问具体属性
console.log(person.name);// Property 'name' does not exist on type 'object'
// ✅ 只能访问 Object 原型上的方法
console.log(person.toString());
我们一般使用接口来定义对象的属性和方法.
// 1. 对象字面量类型(推荐)
const person:{ name:string; age:number}={ name:"Alice", age:25};
// 2. interface
interface Person {
name:string;
age:number;
}
const p: Person ={ name:"Bob", age:30};
// 3. Record
const map: Record<string,number>={ a:1, b:2};
// 4. 索引签名
const dict:{[key:string]:any}={};
dict["name"]="Alice";
dict["age"]=25;
console.log(dict);
// { name: 'Alice', age: 25 }
object vs Object vs {}
| |
|---|
| |
| JS 的 Object 构造函数类型,包含原始类型包装器 |
| 空对象类型,几乎包含所有值(除 null / undefined ) |
// object 不接受原始类型
const x: object ="hello";// ❌ 错误
// Object 接受原始类型(自动装箱)
const y: Object ="hello";// ✅ 可以
需要 具体结构 时:用 interface / 类型别名 / 字面量类型
避免使用 Object 和 {} 作为类型,它们行为怪异
// 定义:第一个元素是 string,第二个是 number
const user:[string,number]=["Alice",25];
// 访问元素(类型已知)
const name = user[0];// string
const age = user[1];// number
// ❌ 越界访问会报错
const x = user[2];// Tuple type '[string, number]' of length '2' has no element at index '2'
// 第三个元素可选
const coords:[number,number,number?]=[10,20];
// 或
const coords2:[number,number,number?]=[10,20,30];
// 前两个固定,后面任意多个 string
const log:[string,string,...string[]]=[
"INFO",
"module",
"detail1",
"detail2",
];
const point:readonly[number,number]=[10,20];
// ❌ 不可修改
point[0]=100;// Cannot assign to '0' because it is a read-only property
const user:[name:string, age:number]=["Alice",25];
// 解构时更有语义
const[name, age]= user;
// useState 返回的就是元组
// [number, Dispatch<<SetStateAction<number>>]
const[count, setCount]=useState(0);
// 函数返回多个值
functiongetUser():[string,number]{
return["Alice",25];
}
// CSV 行解析
const row:[string,string,number,boolean]=["Alice","Engineer",25,true];
push 不会检查类型的安全性,会破坏元组的类型约束。
// ❌ 长度不匹配
const bad:[string,number]=["Alice"];// 缺少元素
const bad2:[string,number]=["Alice",25,1];// 元素过多
// ⚠️ push 不会检查类型安全(设计限制)
const t:[string,number]=["Alice",25];
t.push("extra");// 不报错,但破坏元组约束
在 TypeScript 中, any 是最宽松的类型,表示"任意类型",会关闭该变量的类型检查。
let value:any=4;
value ="hello";// ✅ 不报错
value =true;// ✅ 不报错
value ={};// ✅ 不报错
// 可以访问任意属性、调用任意方法
value.foo.bar();// ✅ 编译不报错(运行可能报错)
// 逐步迁移时,先标记为 any,后续再细化类型
functionlegacyFunction(data:any):any{
return data;
}
// 库没有 @types 声明文件
const untypedLib:any=require("some-untyped-lib");
// JSON 解析结果
const parsed:any=JSON.parse(jsonString);
// 用户输入
const userInput:any=getDynamicData();
// 测试时临时绕过
const temp:any= complicatedObject;
let x:any="hello";
// 以下全部编译通过,但运行时可能崩溃
x.toFixed(2);// ❌ 运行时错误:字符串没有 toFixed
x[999].name;// ❌ 运行时错误
x();// ❌ 运行时错误:不是函数
newx();// ❌ 运行时错误
unknown 是类型安全的 any
let a:any=4;
a.toFixed();// ✅ 编译通过(危险)
let u:unknown=4;
u.toFixed();// ❌ 错误:需要先类型收窄
// unknown 必须检查后才能使用
if(typeof u ==="number"){
u.toFixed();// ✅ 安全
}
// ❌ 滥用 any
functionbad(data:any):any{
return data.map((x)=> x.id);
}
// ✅ 尽量用具体类型或泛型
functiongood<T>(data:T[]):T[]{
return data;
}
// ✅ 不得不用时,优先 unknown
functionbetter(data:unknown):void{
if(Array.isArray(data)){
// 安全使用
}
}
// ✅ 类型断言(明确知道类型时)
functionok(data:unknown){
const str = data asstring;
return str.length;
}
any = 关闭类型检查,编译器不再帮你
能不用就不用,用 unknown 或具体类型替代
遗留代码迁移时可用,但要逐步替换
开启 strict / noImplicitAny 防止隐式扩散
ypeScript 中 unknown 是 类型安全的 any ,表示"值可以是任何类型,但使用前必须先检查"。
let a:unknown="hello";
a =123;
a =true;
// 直接使用会报错
a.toString();// ❌ 错误:'a' is of type 'unknown'
let a:unknown="hello";
// 方式1:typeof 检查
if(typeof a ==="string"){
a.toUpperCase();// ✅ 安全,TS 自动收窄为 string
}
// 方式2:instanceof 检查
if(a instanceofDate){
a.getTime();// ✅ 安全
}
// 方式3:类型断言
(a asstring).toUpperCase();// ✅ 但断言不安全,需确保正确
// 方式4:类型守卫函数
functionisString(x:unknown): x isstring{
returntypeof x ==="string";
}
if(isString(a)){
a.toUpperCase();// ✅ 安全
}
let x:any=1;
let y:string= x;// ✅ 不报错,但运行时可能出错
let a:unknown=1;
let b:string= a;// ❌ 报错
let c:string= a asstring;// ✅ 强制断言
functionparseJSON(json:string):unknown{
returnJSON.parse(json);// 返回 unknown 而不是 any
}
const data =parseJSON('{"name": "张三"}');
// data.name // ❌ 报错,必须先检查
if(typeof data ==="object"&& data !==null&&"name"in data){
console.log(data.name);// ✅ 安全
}
functionprocessInput(input:unknown){
if(typeof input ==="string"){
return input.trim();
}
if(Array.isArray(input)){
return input.length;
}
return input;
}
try{
// ...
}catch(error:unknown){
// TS 4.0+ 推荐 unknown
if(error instanceofError){
console.log(error.message);// ✅ 安全
}
}
能用 unknown 就不用 any — unknown 强制你做类型检查,在编译期捕获错误而不是运行期崩溃。
TypeScript 中 never 表示 永远不会发生的值 的类型,是 所有类型的子类型 。一般用于抛出异常
抛出异常
// 抛出异常,不会正常返回
functionthrowError(msg:string):never{
thrownewError(msg);
}
// 死循环,不会结束
functioninfiniteLoop():never{
while(true){}
}
穷尽检查
配合 switch 或 if-else 确保所有情况都被处理:
typeShape=
|{ kind:"circle"; radius:number}
|{ kind:"square"; side:number}
|{ kind:"triangle"; base:number; height:number};
functiongetArea(shape: Shape):number{
switch(shape.kind){
case"circle":
return Math.PI* shape.radius **2;
case"square":
return shape.side **2;
case"triangle":
return(shape.base * shape.height)/2;
default:
// 如果上面漏了某个 case,这里 shape 就是 never
const _exhaustive:never= shape;
return _exhaustive;
}
}
如果以后给 Shape 添加新类型但忘记处理, never 会报错。
从联合类型中排除
typeA=string|number|never;
// 等价于:type A = string | number
// never 在联合类型中自动被忽略
never= 不可能存在,用于:异常函数、穷尽检查、从联合类型中移除
TypeScript 中 void 表示 函数没有返回值 或 返回值被忽略 。
functionlogMessage(msg:string):void{
console.log(msg);
// 没有 return 语句
}
functiondoSomething():void{
const a =1+2;
// 计算完,不返回结果
}
functionmaybeLog(msg:string):void{
if(!msg)return;// return undefined
console.log(msg);
}
functionf1():void{}
functionf2():undefined{
returnundefined;
}
let a:void=undefined;// ✅
let b:void=null;// ❌ strictNullChecks 下报错
let c:undefined=f1();// ❌ void 不能赋给 undefined
let d:void=f2();// ✅ undefined 可以赋给 void
// 不关心回调的返回值
functionfetchData(callback:(data:string)=>void):void{
const data ="result";
callback(data);// 返回值被忽略
}
fetchData((data)=>{
console.log(data);
return123;// ✅ 允许,但返回值被忽略
});
interfaceLogger{
log(msg:string):void;
error(msg:string):void;
}
classConsoleLoggerimplementsLogger{
log(msg:string):void{
console.log(msg);
}
error(msg:string):void{
console.error(msg);
}
}
const arr =[1,2,3];
// 明确无返回值
arr.forEach((item):void=>{
console.log(item);
});
// 与有返回值的对比
const doubled = arr.map((item):number=>{
return item *2;
});
void = "函数执行了,但什么都不返回"
用于:回调函数、副作用函数、明确忽略返回值