TypeScript中的键和值类型 接口A{A?:number}; 接口B{a?:string}; 功能副本< 源扩展对象, 目标扩展{[destinationKey in keyof Source]?:(1)} >( 资料来源:资料来源, 键:源的键, 目的地:目的地, 变压器:(值:(2))=>(3) ) { 如果(源[键]!==未定义){ 目的地[键]=变压器-变压器(源[键]):源[键]; } } 常数a:a={a:123}; 常数b:b={}; 复制(a,“a”,b,(value)=>value.toString());

TypeScript中的键和值类型 接口A{A?:number}; 接口B{a?:string}; 功能副本< 源扩展对象, 目标扩展{[destinationKey in keyof Source]?:(1)} >( 资料来源:资料来源, 键:源的键, 目的地:目的地, 变压器:(值:(2))=>(3) ) { 如果(源[键]!==未定义){ 目的地[键]=变压器-变压器(源[键]):源[键]; } } 常数a:a={a:123}; 常数b:b={}; 复制(a,“a”,b,(value)=>value.toString());,typescript,generics,types,typescript3.0,Typescript,Generics,Types,Typescript3.0,在上面的示例中,我可以为以下占位符使用什么: (1)-与源中相应键关联的目标中的值类型 (2)-与参数键指定的键相关联的源中的值类型 (3)-与参数键指定的键相关联的目标中的值类型 您需要一个额外的类型参数,表示将传入的实际密钥。此参数将根据传递给键的值推断为字符串文字类型。使用这个新类型,我们可以使用类型查询来获取源和目标类型中类型的特定属性 此外,由于我们只关心特定的K键,因此当我们将目标类型定义为拥有它时,可以使用它(而不是指定目标必须拥有源的所有键)。由于我们并不真正关心目标属性的类型

在上面的示例中,我可以为以下占位符使用什么:

  • (1)-与
    中相应键关联的
    目标
    中的值类型
  • (2)-与参数
    键指定的键相关联的
    中的值类型
  • (3)-与参数
    键指定的键相关联的
    目标
    中的值类型

您需要一个额外的类型参数,表示将传入的实际密钥。此参数将根据传递给
键的值推断为字符串文字类型。使用这个新类型,我们可以使用类型查询来获取
目标
类型中类型的特定属性

此外,由于我们只关心特定的
K
键,因此当我们将
目标
类型定义为拥有它时,可以使用它(而不是指定
目标
必须拥有
的所有键)。由于我们并不真正关心目标属性的类型,只要它存在并且
transformer
函数必须返回一个与此属性类型相同的值,我们就可以在
destination
中将属性的类型指定为
unknown

interface A { a?: number };
interface B { a?: string };

function copy<
    K extends keyof Source, // The extra type parameter
    Source extends object,
    Destination extends { [destinationKey in K]?: unknown } // Can be anything we don't really care, we only care about the K key existing
>(
    source: Source,
    key: K, // The key is of type K
    destination: Destination,
    transformer: (value: Source[K]) => Destination[K] // We use K to specify the relation between Source and Destination property type
) {
    if (source[key] !== undefined) {
        destination[key] = transformer ? transformer(source[key]) : source[key];
    }
}

const a: A = { a: 123 };
const b: B = {};

copy(a, "a", b, (value) => value.toString());
copy(a, "a", b, (value) => value); /// error
接口A{A?:number};
接口B{a?:string};
功能副本<
K扩展了Source的keyof,//额外的类型参数
源扩展对象,
Destination extends{[destinationKey in K]?:unknown}//可以是任何我们并不真正关心的东西,我们只关心存在的K密钥
>(
资料来源:资料来源,
key:K,//该键属于K类型
目的地:目的地,
transformer:(value:Source[K])=>Destination[K]//我们使用K来指定源和目标属性类型之间的关系
) {
如果(源[键]!==未定义){
目的地[键]=变压器-变压器(源[键]):源[键];
}
}
常数a:a={a:123};
常数b:b={};
复制(a,“a”,b,(value)=>value.toString());
复制(a,“a”,b,(值)=>值);//错误