我如何在打字稿中定义这个对象?

时间:2017-12-26 03:19:29

标签: angular typescript

我有以下对象,即我想要强制执行的结构。

{
    '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 }的东西,这让我相信它是可能的。

我可以想到如何将它表示为一个集合,因为那将是一个对象数组,但我不确定我是如何将它描述为一个嵌套的对象结构。

5 个答案:

答案 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, ...

那么你只有那个对象内的那些属性。

你不能影响另一个拥有usernamepasswordGroup等其他财产的对象......

答案 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类,用于在登录变量中插入数据。