简体   繁体   English

打字稿通用函数更改参数类型

[英]Typescript generic function changing argument type

I have a question regarding generic function (specifically why i'm able to modify an object from specific type)我有一个关于泛型函数的问题(特别是为什么我能够修改特定类型的对象)

example :例子 :

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

let user: UserConfig = {
    name: "Eyal",
    age: 23,
 };

function addTimestamp<T>(arg: T): T {
  return { ...arg, timestamp: new Date().toString() };
}

console.log(user); // {name: 'Eyal',age: 23}

user = addTimestamp<UserConfig>(user);

console.log(user); // { name: 'Eyal', age: 23, timestamp: 2022-06-29T16:28:31.524Z }

Why i'm able to mutate user variable when it should have UserConfig interface properties only ( name and age )为什么当它应该只有UserConfig接口属性( nameage )时我能够改变user变量

As this won't work因为这行不通

...
user.timestamp = "xxxx" // ERROR - Property 'timestamp' does not exist on type 'UserConfig'

First, you are not mutating "user", you are creating a new object that has all the fields of user, plus the timestamp field--the original user object doesn't change.首先,您不是在改变“用户”,而是在创建一个新对象,其中包含用户的所有字段以及时间戳字段——原始用户对象不会改变。

TypeScript doesn't complain here because the new object you return is still compatible with the original type T--you've not changed or removed any existing properties, you've just added new ones. TypeScript 在这里没有抱怨,因为您返回的新对象仍然与原始类型 T兼容——您没有更改或删除任何现有属性,您只是添加了新属性。 It's structurally compatible with the original type.它在 结构上与原始类型兼容

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

let user: UserConfig = {
  name: "Eyal",
  age: 23,
};

function addTimestamp<T>(arg: T): T {
  return { ...arg, timestamp: new Date().toString() };
}

let newUser: UserConfig = addTimestamp(user);

console.log(user === newUser); // false
console.log('timestamp' in user); // false
console.log('timestamp' in newUser); // true

let typeTest: UserConfig = (() => {
  return {
    name: 'Pizza',
    age: 49,
    isVeryCool: true
  }
})(); // compiles just fine

// @ts-expect-error
console.log(typeTest.isVeryCool); // doesn't compile if I remove the directive
console.log('isVeryCool' in typeTest); // true

You can argue that this is a weird thing to allow, especially given that TypeScript will block other kinds of related additions (for example, try removing the IIFE from my typeTest example and using the literal directly), but it's technically correct with the rest of the type system rules.你可以争辩说这是一件很奇怪的事情,特别是考虑到 TypeScript 会阻止其他类型的相关添加(例如,尝试从我的 typeTest 示例中删除 IIFE 并直接使用文字),但它在技术上与其余部分是正确的类型系统规则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM