我有以下对象,即我想要强制执行的结构。
{
'username': {
required: 'Please enter your username.'
},
'passwordGroup': {
ocMatchFields: 'Passwords do not match'
},
'passwordGroup.password': {
required: 'Please enter your password'
},
'passwordGroup.confirmPassword': {
required: 'Please confirm your password'
}
}
它永远不会比显示更深入嵌套,并且值将始终是字符串,但可以有任意数量的"字段"。在这种情况下,字段是第一级键。 username,passwordGroup等。
我遇到了一个将对象描述为{ [key: string]: boolean }
的东西,这让我相信它是可能的。
我可以想到如何将它表示为一个集合,因为那将是一个对象数组,但我不确定我是如何将它描述为一个嵌套的对象结构。
答案 0 :(得分:3)
了解TypeScript,我可能忽略了一些令人敬畏的语法。但这是一种方式:
interface KeyValuePair<T> { [key: string]: T };
let x: KeyValuePair<KeyValuePair<string>> = {
'username': {
required: 'Please enter your username.'
},
'passwordGroup': {
ocMatchFields: 'Passwords do not match'
},
'passwordGroup.password': {
required: 'Please enter your password'
},
'passwordGroup.confirmPassword': {
required: 'Please confirm your password'
}
}
请注意,上述内容并不能阻止嵌套对象拥有多个密钥。
或者你可以获得超级通用(但它可能有点过分):
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var hbs = require('express-handlebars');
var debug = require('debug')('to-moon:server');
var http = require('http');
var router = express.Router();
var socket = require('socket.io');
var app = express();
// Server Setup
var port = normalizePort(process.env.PORT || '8000');
app.set('port', port);
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
var io = socket(server);
//pass the parameter to router page app,router,io
var index = require('./routes/index')(app,router,io)
// view engine setup
app.engine('hbs', hbs({extname: 'hbs', defaultLayout: 'layout', layoutsDir: __dirname + '/views/layouts'}));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/js', express.static(__dirname + '/node_modules/bootstrap/dist/js')); // redirect bootstrap JS
app.use('/js', express.static(__dirname + '/node_modules/jquery/dist')); // redirect JS jQuery
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css')); // redirect CSS bootstrap
app.use('/', index);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
答案 1 :(得分:0)
嗯,你可以这样做。
export default [
{
'username': {
required: 'Please enter your username.'
},
'passwordGroup': {
ocMatchFields: 'Passwords do not match'
},
'passwordGroup.password': {
required: 'Please enter your password'
},
'passwordGroup.confirmPassword': {
required: 'Please confirm your password'
}
}
]
稍后,在您的打字稿控制器上,您可以将其导入为您想要的任何内容
import nameYouWant from 'adrees-file-src-exist-json'
答案 2 :(得分:0)
您可以这样声明该类型的对象:
myObject: {
'username': {
required: string
},
'passwordGroup': {
ocMatchFields: string;
},
'passwordGroup.password': {
required: string
},
'passwordGroup.confirmPassword': {
required: string
}
}
这样你就可以做到:
myObject.username, ...
那么你只有那个对象内的那些属性。
你不能影响另一个拥有username
或passwordGroup
等其他财产的对象......
答案 3 :(得分:0)
TypeScript 2.2引入了一种名为object的新类型。它表示任何非基本类型。以下类型被认为是JavaScript中的基本类型:
boolean
number
string
symbol
null
undefined
所有其他类型都被认为是非基本类型。新对象类型恰好代表:
所有原始类型
类型Primitive = |布尔 |数 |串 |符号 |空值 |未定义;
所有非原始类型
输入NonPrimitive = object;
让我们看看object如何让我们编写更准确的类型声明。 使用对象类型
键入声明随着TypeScript 2.2的发布,标准库的类型声明已更新,以使用新的对象类型。例如,Object.create()和Object.setPrototypeOf()方法现在指定类型对象|原型参数为null:
答案 4 :(得分:0)
请在LoginInterface.ts中声明这些类型
export interface IfcRequired {
required: String;
}
export interface IfcOCMatchFields {
ocMatchFields: String;
}
export interface Login {
username: IfcRequired;
password: IfcOCMatchFields;
passwordGroup.password: IfcRequired;
passwordGroup.confirmPassword: IfcRequired;
}
要使用这些界面,请使用
import {IfcRequired, IfcOCMatchFields, Login} from 'LoginInterface';
为声明登录对象数组的类型
let login: Login[];
我建议你创建一个Login类,用于在登录变量中插入数据。