如何在TypeScript中获取源中的实际行号(用于自定义日志记录)

ehi*_*ler 4 javascript node.js typescript electron

引用此问题,我正在使用以下代码来查找我的自定义日志记录函数的调用方的行号:

/**
 * eLog - displays calling line number & message & dumps vars as pretty json string
 * @param {string} msg - string to display in log message
 * @param {any} dispVars - any number of variables (ellipsis , aka Rest parameters) to dump
 */
function eLog(msg:string,...dispVars:any[]){
    let caller_line = (new Error).stack.split("\n")[4];
    console.log(`eLog->Line#${caller_line}->${msg}->`);
    console.log(JSON.stringify((new Error).stack.split("\n"),null,2));
    dispVars.forEach(value => {
        console.log(JSON.stringify(value,null,2));
    });
}
Run Code Online (Sandbox Code Playgroud)

这样称呼:

eLog("eLog Test",this);
Run Code Online (Sandbox Code Playgroud)

尽管这样做确实可以正确转储.js文件行号,但我需要源行号(.ts行号)。如何正确生成?

ehi*_*ler 5

我在晚上经历了这个过程,并想到了一个令我满意的功能。感谢您对入门的帮助-

分离成 log.ts

require('source-map-support').install({
	environment: 'node'
});


/**
 * eLog - displays calling line number & message & dumps vars as pretty json string
 * @param {string} msg - string to display in log message
 * @param {any} dispVars - any number of variables (ellipsis , aka Rest parameters) to dump
 * {@link https://github.com/evanw/node-source-map-support usable by typescript node-source-map-support module}
 * {@link https://github.com/mozilla/source-map/ Mozilla source-map library & project}
 * {@link http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ good introduction to sourcemaps}
 */
export function eLog(msg:string,...dispVars:any[]){
	/**
	 * go one line back for the caller
	 * @type {string}
	 */
	let stackLine = (new Error).stack.split("\n")[2];
	/**
	 * retrieve the file basename & positional data, after the last `/` to the `)` 
	 */
	// 
	let caller_line = stackLine.slice(stackLine.lastIndexOf('/'),stackLine.lastIndexOf(')'))
	/**
	 *  test for no `/` ; if there is no `/` then use filename without a prefixed path
	 */ 
	if ( caller_line.length == 0 ) {
		caller_line = stackLine.slice(stackLine.lastIndexOf('('),stackLine.lastIndexOf(')'))
	}
	// 
	/**
	 * filename_base - parse out the file basename; remove first `/` char and go to `:`
	 */
	let filename_base = caller_line.slice(0+1,caller_line.indexOf(':'));
	/**
	 * line_no - parse out the line number ; remove first `:` char and go to 2nd `:`
	 */
	let line_no = caller_line.slice(caller_line.indexOf(':')+1,caller_line.lastIndexOf(':'));
	/**
	 * line_pos - line positional - from the last `:` to the end of the string
	 */
	let line_pos = caller_line.slice(caller_line.lastIndexOf(':')+1);
	console.log(`eLog called by ${filename_base} on line# ${line_no} @ char# ${line_pos} said:\n${msg}`);
	// print out the input variables as pretty JSON strings
	dispVars.forEach(value => {
		console.log(JSON.stringify(value,null,2));
	});
}
Run Code Online (Sandbox Code Playgroud)

可以简单地调用它:

eLog("eLog Test",this);
Run Code Online (Sandbox Code Playgroud)

只要加载了函数,就可以从任何文件中获取(例如)

import { eLog } from './log'
Run Code Online (Sandbox Code Playgroud)

希望对您有所帮助。

干杯们。-埃里克